是否可以在没有循环的情况下比较T-SQL中的逗号分隔字符串?

时间:2018-03-20 12:25:40

标签: sql sql-server tsql split

我们说我有2个表,其中两个表都有Brand列。该值以逗号分隔,例如,如果其中一个表具有

ACER,ASUS,HP  
AMD,NVIDIA,SONY

作为价值。那么另一张表有

HP,GIGABYTE  
MICROSOFT  
SAMSUNG,PHILIPS

作为价值观。

我想比较这些表以获取所有匹配的记录,在我的示例中ACER,ASUS,HPHP,GIGABYTE匹配,因为它们都有HP。现在我使用循环来实现这一点,我想知道是否可以在单个查询语法中执行此操作。

2 个答案:

答案 0 :(得分:4)

你想要离开循环是正确的。

因为你在2012年,所以String_Split()不在桌面上。但是,野外有任意数量的分割/解析TVF功能。

示例1 - 没有TVF

Declare @T1 table (Brand varchar(50))
Insert Into @T1 values 
('ACER,ASUS,HP'),
('AMD,NVIDIA,SONY')

Declare @T2 table (Brand varchar(50))
Insert Into @T2 values 
('HP,GIGABYTE'),
('MICROSOFT'),
('SAMSUNG,PHILIPS')


Select Distinct
       T1_Brand = A.Brand
      ,T2_Brand = B.Brand
 From ( 
        Select Brand,B.*
         From  @T1
         Cross Apply (
                        Select RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                        From  (Select x = Cast('<x>' + replace(Brand,',','</x><x>')+'</x>' as xml)) as A 
                        Cross Apply x.nodes('x') AS B(i)
                     ) B
      ) A
 Join ( 
        Select Brand,B.*
         From  @T2
         Cross Apply (
                        Select RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                        From  (Select x = Cast('<x>' + replace(Brand,',','</x><x>')+'</x>' as xml)) as A 
                        Cross Apply x.nodes('x') AS B(i)
                     ) B
      ) B
 on A.RetVal=B.RetVal

示例2 - 使用TVF

Select Distinct
       T1_Brand = A.Brand
      ,T2_Brand = B.Brand
 From ( 
        Select Brand,B.*
         From  @T1
         Cross Apply [dbo].[tvf-Str-Parse](Brand,',') B
      ) A
 Join ( 
        Select Brand,B.*
         From  @T2
         Cross Apply [dbo].[tvf-Str-Parse](Brand,',') B
      ) B
 on A.RetVal=B.RetVal

两者都会返回

T1_Brand        T2_Brand
ACER,ASUS,HP    HP,GIGABYTE

感兴趣的UDF

CREATE FUNCTION [dbo].[tvf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
    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(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
--Thanks Shnugo for making this XML safe
--Select * from [dbo].[tvf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[tvf-Str-Parse]('John Cappelletti was here',' ')
--Select * from [dbo].[tvf-Str-Parse]('this,is,<test>,for,< & >',',')

答案 1 :(得分:0)

比较&#34;,&#34;有同样的问题。分隔字符串

你可以使用&#34; XML&#34;这样做并比较输出并返回相同/不同的值:

declare  @TestInput nvarchar(255)
, @TestInput2 nvarchar(255)

set @TestInput = 'ACER,ASUS,HP'
set @TestInput2 = 'HP,GIGABYTE'



;WITH FirstStringSplit(S1) AS
(
 SELECT CAST('<x>' + REPLACE(@TestInput,',','</x><x>') + '</x>' AS XML)
)
,SecondStringSplit(S2) AS
(
SELECT CAST('<x>' + REPLACE(@TestInput2,',','</x><x>') + '</x>' AS XML)
 )

 SELECT STUFF(
 (
SELECT ',' + part1.value('.','nvarchar(max)')
FROM FirstStringSplit
CROSS APPLY S1.nodes('/x') AS A(part1)
WHERE part1.value('.','nvarchar(max)') IN(SELECT B.part2.value('.','nvarchar(max)')
                                              FROM SecondStringSplit 
                                              CROSS APPLY S2.nodes('/x') AS B(part2)
                                              ) 
FOR XML PATH('')
),1,1,'') as [Same Value]

编辑:

更改&#39;东西&#39;到&#39; XML&#39;