我正在寻找最干净的SQL查询来实现以下目标。性能不是那么重要,因为我的数据集很小。
Sample table:
Letter field holding: A, B, C, D, E,
Location field holding: UAE, CANADA, BOSTON, BAHRAIN, FRANCE
我正在寻找一个结果,列出其中包含字母组合的每个字母/位置,因此结果如下:
A-UAE
A-CANADA
A-BAHRAIN
A-FRANCE
B-BOSTON
B-BAHRAIN
C-CANADA
C-FRANCE
D-CANADA
E-UAE
E-FRANCE
答案 0 :(得分:2)
这是另一种解决方案:
DECLARE @Letter TABLE (
letter CHAR(1) PRIMARY KEY
);
DECLARE @Country TABLE (
name VARCHAR(100) PRIMARY KEY
);
INSERT INTO @Letter (letter)
VALUES ('A'), ('B'), ('C'), ('D'), ('E');
INSERT INTO @Country (name)
VALUES ('UAE'), ('CANADA'), ('BOSTON'), ('BAHRAIN'), ('FRANCE');
SELECT CONCAT(L.letter, ' - ', C.name)
FROM @Letter AS L
INNER JOIN @Country AS C
ON C.name LIKE '%' + L.letter + '%'
ORDER BY L.letter, C.name;
结果:
A - BAHRAIN
A - CANADA
A - FRANCE
A - UAE
B - BAHRAIN
B - BOSTON
C - CANADA
C - FRANCE
D - CANADA
E - FRANCE
E - UAE
希望你输出你期望的东西 您可以在堆栈交换数据上运行此查询:https://data.stackexchange.com/stackoverflow/query/622821
或者,如果性能出现问题,您可以创建一个单独的表格,用于存储每个国家/地区名称及其名称。唯一的字母,所以你可以做一个简单的连接,而不是LIKE
来比较事情:
DECLARE @CountrySplit TABLE (
letter CHAR(1)
, name VARCHAR(100)
, PRIMARY KEY (letter, name)
);
INSERT INTO @CountrySplit (letter, name)
SELECT DISTINCT SUBSTRING(C.name, v.number + 1, 1), C.name
FROM @Country AS C
INNER JOIN master..spt_values AS V
ON V.number < LEN(C.name)
WHERE V.type = 'P';
SELECT CONCAT(L.letter, ' - ', CS.name) AS Result
FROM @CountrySplit AS CS
INNER JOIN @Letter AS L
ON L.letter = CS.letter;
这是对堆栈交换数据的查询: https://data.stackexchange.com/stackoverflow/query/622841
对此字符串拆分答案的肯定:T-SQL Split Word into characters
答案 1 :(得分:1)
借助Parse / Split UDF和Cross Apply。
我添加了一个ID来证明可以为整个表运行
示例强>
Declare @YourTable table (ID int,Letter varchar(50),Location varchar(50))
Insert Into @YourTable values
(1,'A, B, C, D, E,','UAE, CANADA, BOSTON, BAHRAIN, FRANCE')
Select A.ID
,B.*
From @YourTable A
Cross Apply (
Select NewValue = B1.RetVal+'-'+B2.RetVal
From [dbo].[udf-Str-Parse](A.Letter,',') B1
Join [dbo].[udf-Str-Parse](A.Location,',') B2
on charindex(B1.RetVal,B2.RetVal)>0
) B
<强>返回强>
ID NewValue
1 A-UAE
1 A-CANADA
1 A-BAHRAIN
1 A-FRANCE
1 B-BOSTON
1 B-BAHRAIN
1 C-CANADA
1 C-FRANCE
1 D-CANADA
1 E-UAE
1 E-FRANCE
UDF(如果需要)
CREATE FUNCTION [dbo].[udf-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].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
--Select * from [dbo].[udf-Str-Parse]('this,is,<test>,for,< & >',',')
编辑 - 没有UDF的选项
Declare @YourTable table (ID int,Letter varchar(50),Location varchar(50))
Insert Into @YourTable values
(1,'A, B, C, D, E,','UAE, CANADA, BOSTON, BAHRAIN, FRANCE')
Select A.ID
,B.*
From @YourTable A
Cross Apply (
Select NewValue = B1.RetVal+'-'+B2.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.Letter,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B1
Join (
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.Location,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B2
on charindex(B1.RetVal,B2.RetVal)>0
) B