SQL Серверная функция сортировки STRING_AGG не работает должным образом - PullRequest
1 голос
/ 18 июня 2020

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

Это код

;with tbl as
(
    select Id,  ClCode, Manager,    ChangeDate
    from (values
    (1, '000005',   'Cierra Vega',      '2017-10-05'),
    (2, '000005',   'Alden Cantrell',   '2017-11-29'),
    (3, '000005',   'Alden Cantrell',   '2017-11-30'),
    (4, '000005',   'Kierra Gentry',    '2018-09-05'),
    (5, '000005',   'Kierra Gentry',    '2018-09-12'),
    (6, '000005',   'Pierre Cox',       '2018-11-06'),
    (7, '000005',   'Thomas Crane',     '2019-09-11'),
    (8, '000005',   'Thomas Crane',     '2019-10-01'),
    (9, '000005',   'Miranda Shaffer',  '2020-04-27'),
    (10,'000360',   'Bradyn Kramer',    '2017-10-06')
    ) as t(Id, ClCode, Manager, ChangeDate)
)
, grouped as                        
(                       
    select c.ClCode
    , count(distinct c.Manager) [ManagerChangesCount]
    , STRING_AGG(c.[Manager], ',') within group (order by c.MinChangeDate) [Managers]
    , STRING_AGG(c.MinChangeDate, ',') within group (order by c.MinChangeDate) [ChangeDates]
    from (                  
        select x.ClCode
        , x.[Manager]
        , min(x.ChangeDate) [MinChangeDate] 
        from tbl x
        group by x.ClCode, x.[Manager]  
    ) c                 
    group by c.ClCode                   
)
select *
from grouped

Мой образец набор данных содержит данные о том, когда (ChangeDate) определенные клиенты (ClCode) сменили своего менеджера (Manager). Это часть реальной таблицы измерений клиентов DWH (SCD типа 2), поэтому эти «дубликаты» просто содержат изменения где-то в других столбцах.

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

ClCode  ManagerChangesCount             Managers                                                                            ChangeDates
000005  6                               Cierra Vega,Alden Cantrell,Kierra Gentry,Pierre Cox,Thomas Crane,Miranda Shaffer    2017-10-05,2017-11-29,2018-09-05,2018-11-06,2019-09-11,2020-04-27
000360  1                               Bradyn Kramer                                                                       2017-10-06

Но на самом деле я получаю результаты без или с какой-то странной сортировкой

ClCode  ManagerChangesCount Managers                                                                                        ChangeDates
000005  6                               Alden Cantrell,Cierra Vega,Kierra Gentry,Miranda Shaffer,Pierre Cox,Thomas Crane    2017-11-29,2017-10-05,2018-09-05,2020-04-27,2018-11-06,2019-09-11
000360  1                               Bradyn Kramer                                                                       2017-10-06

Этот запрос возвращает хорошую сортировку:

  1. , если я удалю , count(distinct c.Manager) [ManagerChangesCount]
  2. , если я удалю строку id = 10 (второй клиент)
  3. если я добавлю условие фильтрации, где where ClCode = '000005'
  4. , если я избавлюсь от повторяющихся строк в наборе данных и удаляю группу по из подзапроса

Но все равно для меня похоже на ошибку ... Я имею ввиду несортированные результаты по моему запросу

Ребята, разобрались, помогите пожалуйста разобраться, почему не работает сортировка

1 Ответ

2 голосов
/ 18 июня 2020

Во-первых, я согласен с тем, что поведение, которое вы получаете, не должно происходить, однако Stack Overflow не предназначен для сообщения об ошибках в приложениях. Для сервера SQL это должно быть сделано на его Azure портале обратной связи .

Что касается решения проблемы, удаление избыточного DISTINCT из COUNT вызывает проблему. исчезнуть. Чтобы реализовать DISTINCT (либо в SELECT DISTINCT, либо в COUNT(DISTINCT {expression})) SQL Сервер должен сначала отсортировать результаты, так как затем он может легко удалить любые значения, которые имеют одинаковую позицию сортировки. В результате эта сортировка выражается в ваших выражениях STRING_AGG, даже если в них есть явное предложение ORDER BY.

Я говорю, что ваш DISTINCT избыточен, потому что в этой точке запроса не будет повторяющихся значений Manager для данного значения ClCode. Это потому, что вы уже сгруппировали в подзапросе как Manager, так и ClCode. Если вы запустите этот запрос в одиночку, вы увидите, что Manager не имеет дубликатов:

WITH tbl AS
    (SELECT Id,
            ClCode,
            Manager,
            ChangeDate
     FROM (VALUES (1, '000005', 'Cierra Vega', '2017-10-05'),
                  (2, '000005', 'Alden Cantrell', '2017-11-29'),
                  (3, '000005', 'Alden Cantrell', '2017-11-30'),
                  (4, '000005', 'Kierra Gentry', '2018-09-05'),
                  (5, '000005', 'Kierra Gentry', '2018-09-12'),
                  (6, '000005', 'Pierre Cox', '2018-11-06'),
                  (7, '000005', 'Thomas Crane', '2019-09-11'),
                  (8, '000005', 'Thomas Crane', '2019-10-01'),
                  (9, '000005', 'Miranda Shaffer', '2020-04-27'),
                  (10, '000360', 'Bradyn Kramer', '2017-10-06')) t (Id, ClCode, Manager, ChangeDate) )
SELECT x.ClCode,
       x.[Manager],
       MIN(x.ChangeDate) AS [MinChangeDate]
FROM tbl x
GROUP BY x.ClCode,
         x.[Manager];

Таким образом, DISTINCT в COUNT просто добавляет накладные расходы для экземпляра , так как это не требуется (SQL Сервер уже отсортировал данные для GROUP BY, так зачем просить его отсортировать их снова?). Если вы используете DISTINCT в уже агрегированном запросе, то, скорее всего, он вам не понадобится.

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