SQL Server - определить комбинации значений и назначить идентификатор комбинации - PullRequest
0 голосов
/ 13 мая 2019

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

Например, комбинация клиентов для продукта «а» - это та же самая комбинация клиентов для продукта «с» (у них обоих есть клиенты 1,2 и 3), поэтому продукты a и c должны иметь один и тот же идентификатор комбинации («группа клиентов»).Тем не менее, продукты не должны принадлежать к одной и той же группе клиентов, если они разделяют только некоторых из одних и тех же клиентов - например, продукт b имеет только клиентов 1 и 2 (не 3), поэтому должна иметь другую группу клиентов для продуктов «a» и «c».

Ввод:

| productid | customerid |
|-----------|------------|
| a         | 1          |
| a         | 2          |
| a         | 3          |
| b         | 1          |
| b         | 2          |
| c         | 3          |
| c         | 2          |
| c         | 1          |
| d         | 1          |
| d         | 3          |
| e         | 1          |
| e         | 2          |
| f         | 1          |
| g         | 2          |
| h         | 3          |

Желаемый вывод:

| productid | customerid | customergroup |
|-----------|------------|---------------|
| a         | 1          | 1             |
| a         | 2          | 1             |
| a         | 3          | 1             |
| b         | 1          | 2             |
| b         | 2          | 2             |
| c         | 3          | 1             |
| c         | 2          | 1             |
| c         | 1          | 1             |
| d         | 1          | 3             |
| d         | 3          | 3             |
| e         | 1          | 2             |
| e         | 2          | 2             |
| f         | 1          | 4             |
| g         | 2          | 5             |
| h         | 3          | 6             |

или просто

| productid | customergroupid |
|-----------|-----------------|
| a         | 1               |
| b         | 2               |
| c         | 1               |
| d         | 3               |
| e         | 2               |
| f         | 4               |
| g         | 5               |
| h         | 6               |

Редактировать: первая версия содержит описаниемои попытки.В настоящее время у меня есть вложенные запросы, которые в основном дают мне столбец для клиентов 1, 2, 3 и т. Д., А затем используют плотный ранг для получения группировки.Проблема в том, что он не является динамическим для разного числа клиентов, и я не знал, с чего начать, чтобы получить динамический результат, как описано выше.Спасибо за ответы.

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

Используя ответ Ларну, я получил результат за 2008 год:

WITH VTE AS(
    SELECT *
    FROM (VALUES('a','1'),
            ('a','2'),
            ('a','3'),
            ('b','1'),
            ('b','2'),
            ('c','3'),
            ('c','2'),
            ('c','1'),
            ('d','1'),
            ('d','3'),
            ('e','1'),
            ('e','2'),
            ('f','1'),
            ('g','2'),
            ('h','3')) V(productid,customerid)),
Groups AS(
    SELECT productid, CustomerIDs = STUFF((SELECT N', ' + customerid 
    FROM VTE AS p2
    WHERE p2.productid = p.productid 
    ORDER BY customerid
    FOR XML PATH(N'')), 1, 2, N'')
    FROM VTE AS p
    GROUP BY productid),
Rankings AS(
    SELECT productid,
           CustomerIDs,
           DENSE_RANK() OVER (ORDER BY CustomerIDs ASC) AS Grouping
    FROM Groups)
SELECT V.productid,
       V.customerid,
       R.Grouping AS customergroupid
FROM VTE V
     JOIN Rankings R ON V.productid = R.productid
ORDER BY V.productid,
         V.customerid;

Еще раз спасибо за вашу помощь.

0 голосов
/ 13 мая 2019

Учитывая, что вы не продемонстрировали свои усилия или не подтвердили используемую вами версию, я предположил, что у вас установлена ​​последняя («самая лучшая») версия SQL Server, что означает, что у вас есть доступ к STRING_AGG.

Это не дает группировку в одном и том же порядке, но я также хочу сказать, что это не имеет значения, и группировка просто произвольна.Это дает вам следующее:

WITH VTE AS(
    SELECT *
    FROM (VALUES('a',1),
            ('a',2),
            ('a',3),
            ('b',1),
            ('b',2),
            ('c',3),
            ('c',2),
            ('c',1),
            ('d',1),
            ('d',3),
            ('e',1),
            ('e',2),
            ('f',1),
            ('g',2),
            ('h',3)) V(productid,customerid)),
Groups AS(
    SELECT productid,
           STRING_AGG(customerid,',') WITHIN GROUP (ORDER BY customerid) AS CustomerIDs
    FROM VTE
    GROUP BY productid),
Rankings AS(
    SELECT productid,
           CustomerIDs,
           DENSE_RANK() OVER (ORDER BY CustomerIDs ASC) AS Grouping
    FROM Groups)
SELECT V.productid,
       V.customerid,
       R.Grouping AS customergroupid
FROM VTE V
     JOIN Rankings R ON V.productid = R.productid
ORDER BY V.productid,
         V.customerid;

db <> fiddle .

Если вы не используете SQL Server 2017, я предлагаю поискать FOR XML PATHметод агрегации строк.

...