我有一个varchar列,该列由另一个我无法控制的进程填充,其中填充了逗号分隔的值。
现在,我需要查找同一列另一行中存在该列一部分的所有行
示例
declare @table table (value varchar(50))
insert into @table values ('NB,BD,FR'), ('BD,GK'), ('SL,SR')
select * from @table
因此表包含
value
-----
NB,BD,FR
BD,GK
SL,SR
从上面的例子中我想得到
value
-----
NB,BD,FR
BD,GK
因为两行中都有一个值(在这种情况下为BD
,但可以是任何值)
这可以在sql中完成吗?
答案 0 :(得分:3)
您可以使用笨拙的XML操作将逗号分隔的值转换为行:
DECLARE @table TABLE (value VARCHAR(50));
INSERT INTO @table VALUES
('NB,BD,FR'),
('BD,GK'),
('SL,SR');
WITH cte AS (
SELECT value, node.value('.', 'varchar(10)') AS substr
FROM @table
CROSS APPLY (SELECT CAST('<x>' + REPLACE(value, ',', '</x>,<x>') + '</x>' AS XML)) AS x(doc)
CROSS APPLY doc.nodes('/x') AS n(node)
)
-- use your favorite technique to find the duplicate
SELECT value
FROM cte AS m
WHERE EXISTS (
SELECT 1
FROM cte AS x
WHERE value <> m.value AND substr = m.substr
)
CAST(... AS XML)
部分假定您的数据不包含在XML中具有特殊含义的字符。 nodes
方法会将一行转换为很多行,其余的将很简单。
答案 1 :(得分:0)
这是错误的数据结构。不要将值存储在字符串中!
declare @table table (id int, value varchar(50));
insert into @table
values (1, 'NB'), (1, 'BD'), (1, 'FR'),
(2, 'BD'), (2, 'GK'),
(3, 'SL'), (3, 'SR');
然后,您可以使用窗口功能获得所需的内容:
select id, value
from (select t.*, max(cnt) over (partition by id) as max_cnt
from (select t.*, count(*) over (partition by value) as cnt
from @table t
) t
) t
where max_cnt >= 2