Найти строки, содержащие одинаковое значение внутри значений, разделенных запятыми - PullRequest
0 голосов
/ 30 января 2019

У меня есть столбец 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?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Вы можете использовать неуклюжие манипуляции с 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 преобразует одну строку во многие, остальное прямо вперед.

0 голосов
/ 30 января 2019

Это неправильная структура данных.Не храните значения в строках!

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
...