2017-02-22 88 views
0

я в следующей таблице TSQL (есть и другие столбцы тоже, но не столбец идентификаторов или основной столбец ключа):TSQL: Найти последовательность PAIR в таблице

Oid Cid 
    1 a 
    1 b 
    2 f 
    3 c 
    4 f 
    5 a 
    5 b 
    6 f 
    6 g 
    7 f 

Таким образом, в приведенном выше примере, я не хотел бы подчеркнуть, что после Oid являются дубликатом при просмотре значений столбцов Cid как «пАР»:

Oid: 
1 (1 matches Oid: 5) 
2 (2 matches Oid: 4 and 7) 

Пожалуйста ЗАМЕТЬТЕ, что матч Oid 2 не включает OID 6, так как пара 6 имеет букву «G», а также.

Возможно ли создать запрос без использования цикла While, чтобы выделить «Oid», как указано выше? наряду с тем, сколько других совпадений существует в базе данных? Я пытаюсь найти шаблоны в наборе данных, относящихся к этим двум столбцам. Заранее спасибо.

+0

Обратите внимание, что это соответствие пара мне нужно сделать, не человек письмо сопоставив. Таким образом, в желаемом наборе результатов для Oid = 2 он не должен содержать сопоставление букв для Oid 6. Так как он имеет букву «G». Надеюсь, что это очистит – hss

ответ

2

Вот это обработанный пример - см комментариев для объяснения:

--First set up your data in a temp table 
declare @oidcid table (Oid int, Cid char(1)); 
insert into @oidcid values 
(1,'a'), 
(1,'b'), 
(2,'f'), 
(3,'c'), 
(4,'f'), 
(5,'a'), 
(5,'b'), 
(6,'f'), 
(6,'g'), 
(7,'f'); 

--This cte gets a table with all of the cids in order, for each oid 
with cte as (
    select distinct Oid, (select Cid + ',' from @oidcid i2 
          where i2.Oid = i.Oid order by Cid 
          for xml path('')) Cids 
    from @oidcid i 
) 
select Oid, cte.Cids 
from cte 
inner join ( 
    -- Here we get just the lists of cids that appear more than once 
    select Cids, Count(Oid) as OidCount 
    from cte group by Cids 
    having Count(Oid) > 1) as gcte on cte.Cids = gcte.Cids 
-- And when we list them, we are showing the oids with duplicate cids next to each other 
Order by cte.Cids 
0
select o1.Cid, o1.Oid, o2.Oid 
    , count(*) + 1 over (partition by o1.Cid) as [cnt] 
from table o1 
join table o2 
    on o1.Cid = o2.Cid 
and o1.Oid < o2.Oid 
order by o1.Cid, o1.Oid, o2.Oid 
+0

Спасибо, что ответили @paparazzi. Это решение не дает правильного ответа для Oid 2. Вместо того, чтобы говорить, что он соответствует «F» 3 раза (для 2, 4 и 7, если включить 2), он говорит, что он соответствует 4 раза (для 2, 4, 6, 7). Мне нужна пара, а не индивидуальное письмо. Поскольку 6 имеет «F» и «G», его не следует выбирать. Извините, если сообщение не было ясно. – hss

0

Может быть, как это тогда:

WITH CTE AS 
(
    SELECT Cid, oid 
    ,ROW_NUMBER() OVER (PARTITION BY cid ORDER BY cid) AS RN 
    ,SUM(1) OVER (PARTITION BY oid) AS maxRow2 
    ,SUM(1) OVER (PARTITION BY cid) AS maxRow 
    FROM oid 
) 
SELECT * FROM CTE WHERE maxRow != 1 AND maxRow2 = 1 
ORDER BY oid 
+0

Благодарим за отзыв @ Owain-Esau. Это решение не дает правильного ответа для Oid 2. Вместо того, чтобы говорить, что он соответствует «F» 3 раза (для 2, 4 и 7, если включить 2), он говорит, что он соответствует 4 раза (для 2, 4, 6, 7). Мне нужна пара, а не индивидуальное письмо. Поскольку 6 имеет «F» и «G», его не следует выбирать. Извините, если сообщение не было ясно – hss