Sql 识别一列中存在但另一列中不存在的不同代码
我的数据如下表所示。前两列是带有管道分隔符的国家/地区代码列表。有两组行的秩分别为1和2。 我试图识别CountryList1中存在的国家代码,但在给定等级上CountryList1列中不存在。对于排名1的行,HN JP SK和KY在CountryList1中存在,但在CountryList2中不存在。同样,对于秩2行。HN存在于CountryList1中,但不存在于CountryList2中。 我期待像第二个表一样的输出。我不想使用函数或过程,而是尝试使用select语句来完成它 输入 输出Sql 识别一列中存在但另一列中不存在的不同代码,sql,sql-server,Sql,Sql Server,我的数据如下表所示。前两列是带有管道分隔符的国家/地区代码列表。有两组行的秩分别为1和2。 我试图识别CountryList1中存在的国家代码,但在给定等级上CountryList1列中不存在。对于排名1的行,HN JP SK和KY在CountryList1中存在,但在CountryList2中不存在。同样,对于秩2行。HN存在于CountryList1中,但不存在于CountryList2中。 我期待像第二个表一样的输出。我不想使用函数或过程,而是尝试使用select语句来完成它 输入 输出
DistinctCountry1 || RAN
====================||========
HN || 1
JP || 1
SK || 1
KY || 1
JP || 2
你的数据结构很糟糕。您应该将列表中的元素作为单独的值存储在行中。但是您可以通过拆分这些值来做一些事情。SQL Server 2016具有
string\u split()
。对于早期版本,您可以在web上找到
with tc as (
select t.*, s.country1
from t cross apply
(string_split(t.countrylist1, '|') s(country1)
)
select distinct t.country1, t.rnk
from tc
where not exists (select 1
from t t2
where tc.rnk = t2.rnk and
tc.country in (select value from string_split(t2.country_list))
);
这是没有效率的。而且,使用现有的数据结构,几乎没有提高性能的余地。您的数据结构很糟糕。您应该将列表中的元素作为单独的值存储在行中。但是您可以通过拆分这些值来做一些事情。SQL Server 2016具有
string\u split()
。对于早期版本,您可以在web上找到
with tc as (
select t.*, s.country1
from t cross apply
(string_split(t.countrylist1, '|') s(country1)
)
select distinct t.country1, t.rnk
from tc
where not exists (select 1
from t t2
where tc.rnk = t2.rnk and
tc.country in (select value from string_split(t2.country_list))
);
这是没有效率的。而且,对于现有的数据结构,几乎没有提高性能的余地。这里有一个很好的循环,您可以使用它:
declare @holding table (country1 varchar(max), country2 varchar(max), rank int)
declare @iterator int=1
declare @countrylistoriginal1 varchar(max)
declare @countrylistoriginal2 varchar(max)
declare @countrylist1 varchar(max)
declare @countrylist2 varchar(max)
declare @rank int
while @iterator<=(select max(rowid) from #temp2)
begin
select @countrylistoriginal1=countrylist1+'|', @rank=[rank]
from yourtable where rowid=@iterator
while @countrylistoriginal1<>''
begin
set @countrylist1=left(@countrylistoriginal1,(charindex('|',@countrylistoriginal1)))
set @countrylistoriginal1=replace(@countrylistoriginal1, @countrylist1,'')
select @countrylistoriginal2=countrylist2+'|'
from yourtable where rowid=@iterator
while @countrylistoriginal2<>''
begin
set @countrylist2=left(@countrylistoriginal2,(charindex('|',@countrylistoriginal2)))
set @countrylistoriginal2=replace(@countrylistoriginal2, @countrylist2,'')
insert @holding
select replace(@countrylist1,'|',''), replace(@countrylist2,'|',''), @rank
end
end
set @iterator=@iterator+1
end
select distinct a.country1, a.rank from @holding a
left join @holding b on a.country1=b.country2 and a.rank=b.rank where b.country2 is null
declare@holding table(country1 varchar(max)、country2 varchar(max)、rank int)
声明@iterator int=1
声明@countrylistoriginal1 varchar(最大值)
声明@countrylistoriginal2 varchar(最大值)
声明@countrylist1 varchar(最大值)
声明@countrylist2 varchar(最大值)
声明@rank int
@iterator这里有一个很好的循环,您可以使用它:
declare @holding table (country1 varchar(max), country2 varchar(max), rank int)
declare @iterator int=1
declare @countrylistoriginal1 varchar(max)
declare @countrylistoriginal2 varchar(max)
declare @countrylist1 varchar(max)
declare @countrylist2 varchar(max)
declare @rank int
while @iterator<=(select max(rowid) from #temp2)
begin
select @countrylistoriginal1=countrylist1+'|', @rank=[rank]
from yourtable where rowid=@iterator
while @countrylistoriginal1<>''
begin
set @countrylist1=left(@countrylistoriginal1,(charindex('|',@countrylistoriginal1)))
set @countrylistoriginal1=replace(@countrylistoriginal1, @countrylist1,'')
select @countrylistoriginal2=countrylist2+'|'
from yourtable where rowid=@iterator
while @countrylistoriginal2<>''
begin
set @countrylist2=left(@countrylistoriginal2,(charindex('|',@countrylistoriginal2)))
set @countrylistoriginal2=replace(@countrylistoriginal2, @countrylist2,'')
insert @holding
select replace(@countrylist1,'|',''), replace(@countrylist2,'|',''), @rank
end
end
set @iterator=@iterator+1
end
select distinct a.country1, a.rank from @holding a
left join @holding b on a.country1=b.country2 and a.rank=b.rank where b.country2 is null
declare@holding table(country1 varchar(max)、country2 varchar(max)、rank int)
声明@iterator int=1
声明@countrylistoriginal1 varchar(最大值)
声明@countrylistoriginal2 varchar(最大值)
声明@countrylist1 varchar(最大值)
声明@countrylist2 varchar(最大值)
声明@rank int
当@iterator尝试这个
表架构和数据
CREATE TABLE [tableName](
[CountryList1] [nvarchar](50) NULL,
[CountryList2] [nvarchar](50) NULL,
[RANK] [int] NULL
)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN|IN|US', N'GB|CA|CH|CA', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'JP|CH ', N'IN|US|LU', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN|SK|KY', N'GB|CA', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'FI', N'IN|MO', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN|IN|US', N'HN ', 2)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'JP|CH', N'CH|IN|US', 2)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN', N'NO', 2)
SQL查询
;WITH cte AS
( SELECT DISTINCT *
FROM (SELECT [value] AS DistinctCountry1,
[rank],
Rtrim(Ltrim([value])) + Cast([rank] AS NVARCHAR(max)) AS colX
FROM tablename
CROSS apply String_split([countrylist1], '|')) tmp
WHERE colx NOT IN (SELECT Rtrim(Ltrim([value])) + Cast([rank] AS NVARCHAR(max)) AS colX
FROM tablename
CROSS apply String_split([countrylist2], '|'))
)
SELECT [distinctcountry1], [rank]
FROM cte
ORDER BY [rank]
输出
+------------------+------+
| distinctcountry1 | rank |
+------------------+------+
| FI | 1 |
| HN | 1 |
| JP | 1 |
| KY | 1 |
| SK | 1 |
| JP | 2 |
+------------------+------+
演示:
注意:正如其他人已经提出的,你确实应该考虑修复你的表,或者在处理数据时必须额外花费时间。p> 试试这个
表架构和数据
CREATE TABLE [tableName](
[CountryList1] [nvarchar](50) NULL,
[CountryList2] [nvarchar](50) NULL,
[RANK] [int] NULL
)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN|IN|US', N'GB|CA|CH|CA', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'JP|CH ', N'IN|US|LU', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN|SK|KY', N'GB|CA', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'FI', N'IN|MO', 1)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN|IN|US', N'HN ', 2)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'JP|CH', N'CH|IN|US', 2)
INSERT [tableName] ([CountryList1], [CountryList2], [RANK]) VALUES (N'HN', N'NO', 2)
SQL查询
;WITH cte AS
( SELECT DISTINCT *
FROM (SELECT [value] AS DistinctCountry1,
[rank],
Rtrim(Ltrim([value])) + Cast([rank] AS NVARCHAR(max)) AS colX
FROM tablename
CROSS apply String_split([countrylist1], '|')) tmp
WHERE colx NOT IN (SELECT Rtrim(Ltrim([value])) + Cast([rank] AS NVARCHAR(max)) AS colX
FROM tablename
CROSS apply String_split([countrylist2], '|'))
)
SELECT [distinctcountry1], [rank]
FROM cte
ORDER BY [rank]
输出
+------------------+------+
| distinctcountry1 | rank |
+------------------+------+
| FI | 1 |
| HN | 1 |
| JP | 1 |
| KY | 1 |
| SK | 1 |
| JP | 2 |
+------------------+------+
演示:
注意:正如其他人已经提出的,你确实应该考虑修复你的表,或者在处理数据时必须额外花费时间。p> 修复您的数据结构,使其不令人讨厌。在一列中存储多个值的形式不好。正确,但我现在无法更改数据。您是否使用
数组
类型?您应该规范化数据库。SQL与您正在使用的数据结构变得错综复杂。@TheImpler。SQL Server有一个数组数据类型?'FI'应该在您的最终输出中,并修复您的数据结构,使其不令人讨厌。在一列中存储多个值的形式不好。正确,但我现在无法更改数据。您是否使用数组
类型?您应该规范化数据库。SQL与您正在使用的数据结构变得错综复杂。@TheImpler。SQL Server有一个数组数据类型?'FI'也应该在最终输出中