ВЫБЕРИТЕ DISTINCT для групп данных - PullRequest
5 голосов
/ 25 ноября 2010

У меня есть следующая таблица:

ID  Data
1   A
2   A
2   B
3   A
3   B
4   C
5   D 
6   A
6   B

и т. Д.Другими словами, у меня есть группы данных для каждого идентификатора.Вы заметите, что группа данных (A, B) встречается несколько раз.Я хочу запрос, который может идентифицировать отдельные группы данных и нумеровать их, например:

DataID     Data
101        A
102        A
102        B
103        C
104        D

Таким образом, DataID 102 будет напоминать данные (A, B), DataID 103 будет напоминать данные (C) и т.д.Чтобы можно было переписать мою исходную таблицу в такой форме:

ID   DataID
1    101
2    102
3    102
4    103
5    104
6    102

Как я могу это сделать?


PS.Код для генерации первой таблицы:

CREATE TABLE #t1 (id INT, data VARCHAR(10))
INSERT INTO #t1
SELECT 1, 'A'
UNION ALL SELECT 2, 'A'
UNION ALL SELECT 2, 'B'
UNION ALL SELECT 3, 'A'
UNION ALL SELECT 3, 'B'
UNION ALL SELECT 4, 'C'
UNION ALL SELECT 5, 'D'
UNION ALL SELECT 6, 'A'
UNION ALL SELECT 6, 'B'

Ответы [ 4 ]

3 голосов
/ 25 ноября 2010

По моему мнению, вам нужно создать собственный агрегат, который объединяет данные (в случае строк подход CLR рекомендуется по соображениям производительности). Затем я бы сгруппировал по идентификатору и выбрал отличную от группировки, добавив функцию row_number () или добавив по вашему выбору density_rank (). Во всяком случае, это должно выглядеть так

with groupings as (
select concat(data) groups
from Table1
group by ID
)
select groups, rownumber() over () from groupings
2 голосов
/ 25 ноября 2010

Следующий запрос с использованием CASE даст вам результат, показанный ниже.

С этого момента получение отдельных групп данных и дальнейшие действия не должны быть проблемой.

SELECT     
    id, 
     MAX(CASE data WHEN 'A' THEN data ELSE '' END) + 
     MAX(CASE data WHEN 'B' THEN data ELSE '' END) + 
     MAX(CASE data WHEN 'C' THEN data ELSE '' END) + 
     MAX(CASE data WHEN 'D' THEN data ELSE '' END) AS DataGroups
FROM  t1
GROUP BY id

ID  DataGroups
1   A
2   AB
3   AB
4   C
5   D
6   AB

Однако такая логика будет работать только в том случае, если значения «данных» фиксированы и известны заранее.

В вашем случае вы говорите, что это так. Однако, учитывая, что вы также говорите, что их 1000, это, откровенно говоря, смешной вопрос наверняка: -)

Предложение LuckyLuke, приведенное выше, откровенно говоря, будет более общим и, возможно, более разумным способом реализации решения, хотя в вашем случае.

0 голосов
/ 25 ноября 2010

Просто, чтобы поделиться своим собственным грязным решением, которое я сейчас использую:

SELECT DISTINCT t1.id, D.data
FROM #t1 t1
CROSS APPLY ( 
    SELECT CAST(Data AS VARCHAR) + ','
    FROM #t1 t2
    WHERE t2.id = t1.id
    ORDER BY Data ASC
    FOR XML PATH('') )  
D ( Data )

И затем аналог аналогичного решения LuckyLuke.

0 голосов
/ 25 ноября 2010

Исходя из данных вашего примера (добавив отсутствующий кортеж 2, «A»), вы получите перенумерованные (и уникальные) данные:

with NonDups as (
select t1.id
from #t1 t1 left join #t1 t2
on t1.id > t2.id and t1.data = t2.data
group by t1.id
having COUNT(t1.data) > COUNT(t2.data)
), DataAddedBack as (
    select ID,data
    from #t1 where id in (select id from NonDups)
), Renumbered as (
    select DENSE_RANK() OVER (ORDER BY id) as ID,Data from DataAddedBack
)
select * from Renumbered

Предоставление:

1          A
2          A
2          B
3          C
4          D

Я думаю, что это вопрос реляционного деления, чтобы сопоставить строки из этого вывода со строками в исходной таблице.

...