Определение наборов связанных идентификаторов в SQL Server - PullRequest
4 голосов
/ 28 июля 2011

У меня есть простая таблица, которая выглядит следующим образом:

ClientID    ItemID
1           1
1           2
1           3
2           1
2           2
3           3
4           3
5           1
5           2
5           4
5           5

, где оба столбца объединяются в качестве первичного ключа.Теперь мне поручено определить все уникальные наборы ItemID, назначенных для ClientID.Таким образом, в моем примере наборы были бы:

ItemIDs 1,2,3 (used by ClientID 1)
ItemIDs 1,2 (used by ClientID 2)
ItemIDs 3 (used by ClientIDs 3 and 4)
ItemIDs 1,2,4,5 (used by ClientID 5)

В идеале выходные данные были бы двумя таблицами:

SetID    ItemID
1        1
1        2
1        3
2        1
2        2
3        3
4        1
4        2
4        4
4        5

ClientID    SetID
1           1
2           2
3           3
4           3
5           4

, где SetID было бы новым полем для использования в другом месте.

В настоящее время способ идентификации уникальных наборов состоит в том, чтобы использовать курсор для построения строки упорядоченных ItemID для каждого ClientID, затем сравнивать выходные данные для получения уникальных строк и, наконец, анализировать их обратно.Это было достаточно быстро, чтобы писать, но кажется ужасным.

Я уверен, что должен быть лучший способ, чем этот.Есть идеи?

1 Ответ

1 голос
/ 28 июля 2011
-- Table to hold test data
declare @T table
(
  ClientID int,
  ItemID int
)

insert into @T values
(1, 1),(1, 2),(1, 3),
(2, 1),(2, 2),
(3, 3),(4, 3),
(5, 1),(5, 2),(5, 4),(5, 5)


-- Temp table that will hold the generated set's
declare @Tmp table
(
  ClientID int,
  ItemIDSet varchar(max),
  SetID int
)

-- Query the sets using rank() over a comma separated ItemIDSet
insert into @Tmp
select ClientID,
       ItemIDSet,
       rank() over(order by ItemIDSet) as SetID
from (
      select T1.ClientID,
             stuff((select ','+cast(T2.ItemID as varchar(10))
                    from @T as T2
                    where T1.ClientID = T2.ClientID
                    order by T2.ItemID
                    for xml path('')), 1, 1, '') as ItemIDSet
      from @T as T1
      group by T1.ClientID
     ) as T

-- Get ClientID and SetID from @Tmp
select ClientID, 
       SetID
from @Tmp
order by ClientID

-- Get SetID and ItemID from @Tmp
select SetID,
       T3.N.value('.', 'int') as ItemID
from ( 
       select distinct
              SetID,
              '<i>'+replace(ItemIDSet, ',', '</i><i>')+'</i>' as ItemIDSet
       from @Tmp
     ) as T1
  cross apply 
     ( 
       select cast(T1.ItemIDSet as xml) as ItemIDSet
     ) as T2
  cross apply T2.ItemIDSet.nodes('i') as T3(N)

Результат:

ClientID    SetID
----------- -----------
1           2
2           1
3           4
4           4
5           3

SetID       ItemID
----------- -----------
1           1
1           2
2           1
2           2
2           3
3           1
3           2
3           4
3           5
4           3

Значения SetID не совсем такие же, как в предоставленных вами результатах, но я не думаю, что это будет большой проблемой. SetID генерируются из функции ранга rank() over(order by ItemIDSet), упорядоченной ItemIDSet.

Возьми его за спин .

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