Выявление дублирующих групп данных в SQL - PullRequest
3 голосов
/ 12 декабря 2011

Мой вопрос заключается в том, как определить повторяющиеся (повторяющиеся) группы данных в таблице SQL.В настоящее время я использую SQL Server 2005, поэтому я предпочитаю решения, основанные на этом или ansi-sql.

Вот пример таблицы и ожидаемый результат (ниже), на котором будет основываться этот вопрос:

declare @data table (id nvarchar(10), fund nvarchar(1), xtype nvarchar(1))

insert into @data select 'Switch_1', 'A', 'S'
insert into @data select 'Switch_1', 'X', 'B'
insert into @data select 'Switch_1', 'Y', 'B'
insert into @data select 'Switch_1', 'Z', 'B'
insert into @data select 'Switch_2', 'A', 'S'
insert into @data select 'Switch_2', 'X', 'B'
insert into @data select 'Switch_2', 'Y', 'B'
insert into @data select 'Switch_2', 'Z', 'B'
insert into @data select 'Switch_3', 'C', 'S'
insert into @data select 'Switch_3', 'D', 'B'
insert into @data select 'Switch_4', 'C', 'S'
insert into @data select 'Switch_4', 'F', 'B'

(новые данные)

insert into @data select 'Switch_5', 'A', 'S'
insert into @data select 'Switch_5', 'X', 'B'
insert into @data select 'Switch_5', 'Y', 'B'
insert into @data select 'Switch_5', 'Z', 'B'

--   id         fund xtype match
--   ---------- ---- ----- ---------
--   Switch_1   A    S     Match_1
--   Switch_1   X    B     Match_1
--   Switch_1   Y    B     Match_1
--   Switch_1   Z    B     Match_1
--   Switch_2   A    S     Match_1
--   Switch_2   X    B     Match_1
--   Switch_2   Y    B     Match_1
--   Switch_2   Z    B     Match_1
--   Switch_3   C    S     
--   Switch_3   D    B     
--   Switch_4   C    S     
--   Switch_4   F    B  

(новые результаты)

--   Switch_5   A    S     Match_1
--   Switch_5   X    B     Match_1
--   Switch_5   Y    B     Match_1
--   Switch_5   Z    B     Match_1

Я хочу совпадения только на основе ALL или NOTHING (т. Е. Все записи всоответствие группы всем записям в другой группе - не совпадение по частям).Можно использовать любой идентификатор совпадения (я использовал Match_1 выше, но может быть числовым и т. Д.)

Спасибо за любую помощь здесь.

(РЕДАКТИРОВАТЬ: я думаю, я должен добавить, что может быть любое количество строк в группе, а не только 2 или 4, показанные в примере выше - и я также пытаюсь избегать курсоров)

(РЕДАКТИРОВАТЬ 2: Кажется, у меня проблема, если найдено более одного совпадения. Выходные данные из поставляемого SQL возвращают дубликаты записей для Switch_1, когда найдено более одного совпадения. Я соответственно обновил пример данныхНе уверен, что Ливен все еще следит за этим - я также смотрю на решение и опубликую здесь, если найдут.)

Ответы [ 2 ]

2 голосов
/ 12 декабря 2011

Ход выполнения выглядит следующим образом

  • q: Объедините все фонды и типы одного идентификатора в одну строку, используя XML PATH конструкция
  • r: выберите ROW_NUMBER и соответствующие идентификаторы для соответствующих групп
  • Выберите результаты по левому соединению @data и r

Оператор SQL

;WITH q AS (
  SELECT  DISTINCT d.id
          , DuplicateData = STUFF((SELECT ', ' + fund  + xtype FROM @data WHERE id = d.id FOR XML PATH('')), 1, 2, '')
  FROM    @data d
) 
, r AS (
  SELECT  id1 = q1.id
          , id2 = q2.id
          , rn = ROW_NUMBER() OVER (ORDER BY q1.ID)
  FROM    q q1
          INNER JOIN q q2 ON q1.DuplicateData = q2.DuplicateData AND q1.id < q2.id
)
SELECT  id
        , fund
        , xtype
        , match = 'Match_' + CAST(r.rn AS VARCHAR(32))
FROM    @data d
        LEFT OUTER JOIN r ON d.id IN (r.id1, r.id2)

Результаты

id         fund xtype match
---------- ---- ----- --------------------------------------
Switch_1   A    S     Match_1
Switch_1   X    B     Match_1
Switch_1   Y    B     Match_1
Switch_1   Z    B     Match_1
Switch_2   A    S     Match_1
Switch_2   X    B     Match_1
Switch_2   Y    B     Match_1
Switch_2   Z    B     Match_1
Switch_3   C    S     NULL
Switch_3   D    B     NULL
Switch_4   C    S     NULL
Switch_4   F    B     NULL
1 голос
/ 12 декабря 2011

Вот еще один запрос к нему:

create table #temp1 (
id varchar(10),
fund nvarchar(1),
xtype nvarchar(1)
)

insert into #temp1 select 'Switch_1', 'A', 'S'
insert into #temp1 select 'Switch_1', 'X', 'B'
insert into #temp1 select 'Switch_1', 'Y', 'B'
insert into #temp1 select 'Switch_1', 'Z', 'B'
insert into #temp1 select 'Switch_2', 'A', 'S'
insert into #temp1 select 'Switch_2', 'X', 'B'
insert into #temp1 select 'Switch_2', 'Y', 'B'
insert into #temp1 select 'Switch_2', 'Z', 'B'
insert into #temp1 select 'Switch_3', 'C', 'S'
insert into #temp1 select 'Switch_3', 'D', 'B'
insert into #temp1 select 'Switch_4', 'C', 'S'
insert into #temp1 select 'Switch_4', 'F', 'B'

select t1.*, case when t2.equal = t3.total then 'True' else 'False' end as 'Match' from #temp1 t1
left outer join (select m.id, count(m2.id) as 'equal' from #temp1 m
inner join #temp1 m2 on m.Id <> m2.Id and m.fund = m2.fund and m.xtype = m2.xtype
group by m.id) t2 on t1.id = t2.id
inner join (select m3.id, count(m3.fund) as 'total' from #temp1 m3 group by m3.id) t3 on t3.id = t1.id


drop table #temp1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...