Как использовать SQL PIVOT для нескольких агрегатов? - PullRequest
2 голосов
/ 28 января 2020

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

╔════════════════════╦════════════════╦══════════════╦══════════════════╗
║       Topic        ║     Person     ║ PersonsReply ║  PersonsComment  ║
╠════════════════════╬════════════════╬══════════════╬══════════════════╣
║ Is the earth flat? ║ This Person    ║ Yes          ║ It's flat.       ║
║ Is the earth flat? ║ That Person    ║ No           ║ It's round       ║
║ Is the earth flat? ║ Another Person ║ Maybe        ║ Don't care.      ║
╚════════════════════╩════════════════╩══════════════╩══════════════════╝

Но из примеров, которые я видел в Интернете, я не могу преобразовать свои данные в табличное представление, как показано ниже:

╔════════════════════╦══════════════════╦══════════════════╦═════════════════════╦════════════════════╦════════════════════╦═══════════════════════╗
║       Topic        ║ ThisPersonsReply ║ ThatPersonsReply ║ AnotherPersonsReply ║ ThisPersonsComment ║ ThatPersonsComment ║ AnotherPersonsComment ║
╠════════════════════╬══════════════════╬══════════════════╬═════════════════════╬════════════════════╬════════════════════╬═══════════════════════╣
║ Is the earth flat? ║ Yes              ║ No               ║ Maybe               ║ It's flat          ║ It's round         ║ Don't care            ║
╚════════════════════╩══════════════════╩══════════════════╩═════════════════════╩════════════════════╩════════════════════╩═══════════════════════╝

Как я могу использовать функцию PIVOT SQL для того, чего я пытаюсь достичь? Вот моя песочница: http://sqlfiddle.com/#! 18 / e198d / 1

Сейчас я получаю:

topic   ThisReply   ThatReply   AnotherReply
Is the earth flat?  (null)  (null)  (null)

Ответы [ 3 ]

2 голосов
/ 28 января 2020

Требуется условная агрегация:

select topic,
       max(case when Person = 'This' then reply end) as ThisPersonsReply,
       max(case when Person = 'That' then reply  end) as ThatPersonsReply,
       max(case when Person = 'Another' then reply  end) as AnotherPersonsReply,
       max(case when Person = 'This' then comment end) as ThisPersonsComment,
       max(case when Person = 'That' then comment end) as ThatPersonsComment,
       max(case when Person = 'Another' then comment end) as AnotherPersonsComment
from ptest pt
group by topic;

Здесь DB fiddle.

2 голосов
/ 28 января 2020

Если вы хотите использовать нединамический c PIVOT, он становится малым с CROSS APPLY

Пример

SELECT  *
FROM (
    SELECT topic
          ,B.*
    FROM ptest
    Cross Apply (values (person+'Reply',reply)
                       ,(person+'Comment',comment)

                )B(Item,Value)
) AS source
PIVOT ( max(value) FOR item IN ([ThisReply], [ThatReply], [AnotherReply],[ThisComment], [ThatComment], [AnotherComment]) ) AS pivotTable

Возвращает

topic               ThisReply   ThatReply   AnotherReply    ThisComment ThatComment AnotherComment
Is the earth flat?  Yes         No          Maybe           Its flat    Its round   Dont care
1 голос
/ 28 января 2020

Я бы предложил использовать условную агрегацию для поворота вашего набора данных:

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

  • обычно он работает по крайней мере так же хорошо, как и вендоры c реализации

  • еще одно преимущество заключается в том, что вы можете обрабатывать более сложные агрегаты выражений, чем при использовании pivot (что не относится к вашему вопросу, но может в конечном итоге возникнуть)

Запрос:

select 
    topic,
    max(case when person = 'This person' then personsReply end) ThisPersonsReply,
    max(case when person = 'That person' then personsReply end) ThatPersonsReply,
    max(case when person = 'Another person' then personsReply end) AnotherPersonsReply,
    max(case when person = 'This person' then personsComment end) ThisPersonsComment,
    max(case when person = 'That person' then personsComment end) ThatPersonsComment,
    max(case when person = 'Another person' then personsComment end) AnotherPersonsComment
from ptest 
group by topic

Демонстрация на DB Fiddle :

topic              | ThisPersonsReply | ThatPersonsReply | AnotherPersonsReply | ThisPersonsComment | ThatPersonsComment | AnotherPersonsComment
:----------------- | :--------------- | :--------------- | :------------------ | :----------------- | :----------------- | :--------------------
Is the earth flat? | Yes              | No               | Maybe               | Its flat           | Its round          | Dont care            
...