繁体   English   中英

如何在SQL SELECT替换中使用通配符

[英]How to use wildcards in SQL SELECT Replace

我有一个名为Event的字段,它包含如下数据:

视图:

ID Event
1  2015-T4-C 
2  2015-G4-C
3  2015-T4-C; 2015-R4-C; 2015-Z4-C
4  2018-T4-C
5  2015-T4-Z

使用SQL SELECT(MSSQL),如何使用通配符替换字符串的通配符部分?

例如,这是我试图做的,尽管没有用。 替换的第一次出现是为了满足只有一个实例的值,第二次替换是为了满足具有多个带有';的实例的值。 ' 在他们中:

SELECT
REPLACE(REPLACE(view.Event, '_____T___', ''), '_____T___; ', '')
FROM view

我正在寻找的结果是:

查看结果

ID Event
1    
2  2015-G4-C
3  2015-R4-C; 2015-Z4-C
4  
5

谢谢

编辑:``T''有多个实例,例如2017-T4-C,2018-T4-C,2019-T4-C,2015-T4-Z,因此不能在``2015-T4-C''上使用替换

编辑2:

ps它是这样开始的

原始表

ID Event
1  2015-T4-C 
2  2015-G4-C
3  2015-T4-C 
3  2015-R4-C
3  2015-Z4-C
etc

然后,我使用一个东西XML查询将它们放在同一行,例如

3  2015-T4-C; 2015-R4-C; 2015-Z4-C

编辑3-现在,我知道通配符在SELECT中是不可能的,它改变了问题。 我正在寻找的结果是:

ID EventFilter1           EventFilter2
1                         2015-T4-C
2  2015-G4-C
3  2015-R4-C; 2015-Z4-C   2015-T4-C
4                         2018-T4-C
5                         2015-T4-Z

我可以回头以另一种方式从原始表中提取数据:

原始表

ID Event
1  2015-T4-C 
2  2015-G4-C
3  2015-T4-C 
3  2015-R4-C
3  2015-Z4-C
etc

编辑4:这是一个新问题,知道不可能使用通配符:

你好

我有一个用于客户的表,一个事件表。 每个客户有多个事件。 我需要导出到以分号分隔的单行以进行外部系统导入,根据过滤器将结果分为两列。

事件表:

ID Event
1  2015-T4-C 
2  2015-G4-C
3  2015-T4-C 
3  2015-R4-C 
3  2015-Z4-C
4  2018-T4-C 
4  2018-T4-W
4  2018-K4-I
4  2018-Z4-W
5  2015-T4-Z

所需结果:

ID EventFilter1(T)       EventFilter2(notT)
1  2015-T4-C
2                        2015-G4-C
3  2015-T4-C             2015-R4-C; 2015-Z4-C
4  2018-T4-C; 2018-T4-W  2018-K4-I; 2018-Z4-W    
5  2015-T4-Z 

目前,我只使用两个单独的联接,但只想简单地使用一个联接并加快联接速度。 这是我目前的工作,该如何简化? 目标1是使速度更快,目标2是使速度更简单,但乐于提倡速度胜于简单性。

SELECT c.ID, e.EventFilter1(T), e2.EventFilter2(notT)
FROM Customers c
LEFT JOIN (SELECT 
           c.ID, 
           EventFilter1(T) = STUFF((
                  SELECT distinct '; ' + e.Event
                  FROM Events e
                  WHERE c.ID = e.ID AND Event like '%-T%'
                  FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
            FROM Customers c WHERE c.ID in (SELECT ID FROM Events)) as e
on c.ID = e.ID
LEFT JOIN (SELECT 
           c.ID, 
           EventFilter2(notT) = STUFF((
                  SELECT distinct '; ' + e2.Event
                  FROM Events e2
                  WHERE c.ID = e2.ID AND Event not like '%-T%'
                  FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
            FROM Customers c WHERE c.ID in (SELECT ID FROM Events)) as e2
on c.ID = e2.ID

那么有没有办法我可以在联接子查询中没有过滤器的情况下提取所有数据,然后在主查询中过滤并拆分数据,或者我可以在一个子查询中使用两个过滤器提取两组数据? 例如:

LEFT JOIN (SELECT 
       c.ID, 
       EventFilter1(T) = STUFF((
              SELECT distinct '; ' + e.Event
              FROM Events e
              WHERE c.ID = e.ID AND Event like '%-T%'
              FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
      EventFilter2(notT) = STUFF(( **** What do I put here? ****
        FROM Customers c WHERE c.ID in (SELECT ID FROM Events)) as e
on c.ID = e.ID

借助CROSS APPLY和少量XML作为拆分器

Declare @YourTable table (ID int, [Event] varchar(500))
Insert Into @YourTable values
(1,  '2015-T4-C'), 
(2,  '2015-G4-C'),
(3,  '2015-T4-C; 2015-R4-C; 2015-Z4-C'),
(4,  '2018-T4-C'),
(5,  '2015-T4-Z')

Declare @Pattern varchar(100) = '_____T___'

Select A.ID
      ,NewVal =IsNull(B.S,'')
 From  @YourTable A
 Cross Apply (
                Select S = Stuff((Select '; ' +RetVal 
                  From (
                        Select RetSeq = Row_Number() over (Order By (Select null))
                              ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                        From  (Select x = Cast('<x>' + replace((Select replace(A.[Event],';','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                        Cross Apply x.nodes('x') AS B(i)
                       ) B1
                  Where PatIndex(@Pattern,RetVal)=0
                  Order by RetSeq
                  For XML Path ('')),1,2,'') 
             ) B

退货

ID  NewVal
1   
2   2015-G4-C
3   2015-R4-C; 2015-Z4-C
4   
5   

我认为原始问题是不完整的...我们看到的数据是xml之上的内容,因此应首先清除原始表以获取正确的结果。

请针对原始事件表在tbevents下找到以下解决方案。

create table #tbpattern(
myPat varchar(10) 
)

insert into #tbpattern
values ('T1'),('T2'),('T3'),('T4-C'),('T4-Z')

select * from #tbpattern


create table #tbevents
(
eventid varchar(1000) 
)


insert into #tbevents 
values ('2015-T4-C'),('2015-G4-C'),('2015-Z4-C'),('2018-T4-C'),('2015-T4-Z')


select e.eventid
from #tbevents e
where not exists
(
select 1 from #tbpattern p where charindex(p.myPat,e.eventid) > 0
)



drop table #tbpattern
drop table #tbevents

根据上面的结果应用STUFF

您有固定长度的字符串。 这确实为您提供了一些选择。 这是一个相当痛苦的例子:

select (case when substr(t.event, 6, 1) = 'T'
             then stuff(t.event, 1, 11, '')
             when substr(t.event, 17, 1) = 'T'
             then stuff(t.event, 12, 11, '')
             when substr(t.event, 28, 1) = 'T'
             then stuff(t.event, 23, 11, '')
             . . .
         end)

这确实具有只删除一个的缺点。

我添加了另一个答案,因为“编辑”与原始问题有所出入

Declare @YourTable table (ID int, [Event] varchar(50))
Insert Into @YourTable values
(1  ,'2015-T4-C'), 
(2  ,'2015-G4-C'),
(3  ,'2015-T4-C'),
(3  ,'2015-R4-C'),
(3  ,'2015-Z4-C'),
(4  ,'2018-T4-C'), 
(4  ,'2018-T4-W'),
(4  ,'2018-K4-I'),
(4  ,'2018-Z4-W'),
(5  ,'2015-T4-Z')

Declare @Pattern varchar(100) = '_____T___' 

Select A.ID
      ,NewCol1 = IsNull(B.S,'')
      ,NewCol2 = IsNull(C.S,'')
 From  (Select Distinct ID from @YourTable) A
 Cross Apply (
               Select S = Stuff((Select Distinct '; ' +[Event] 
                 From @YourTable
                 Where PatIndex(@Pattern,[Event])=0
                    and ID = A.ID
                 For XML Path ('')),1,2,'') 
             ) B
 Cross Apply (
               Select S = Stuff((Select Distinct '; ' +[Event] 
                 From @YourTable
                 Where PatIndex(@Pattern,[Event])>0
                    and ID = A.ID
                 For XML Path ('')),1,2,'') 
             ) C

退货

ID  NewCol1                 NewCol2
1                           2015-T4-C
2   2015-G4-C   
3   2015-R4-C; 2015-Z4-C    2015-T4-C
4   2018-K4-I; 2018-Z4-W    2018-T4-C; 2018-T4-W
5                           2015-T4-Z

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM