【问题标题】:How do I use SQL PIVOT for multiple aggregates?如何将 SQL PIVOT 用于多个聚合?
【发布时间】:2020-05-14 00:29:20
【问题描述】:

我有一个如下所示的源表:

╔════════════════════╦════════════════╦══════════════╦══════════════════╗
║       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            ║
╚════════════════════╩══════════════════╩══════════════════╩═════════════════════╩════════════════════╩════════════════════╩═══════════════════════╝

如何使用 SQL 的 PIVOT 函数来实现我想要实现的目标?这是我的沙盒:http://sqlfiddle.com/#!18/e198d/1

现在我得到:

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

【问题讨论】:

  • 我猜您需要返回动态列数?

标签: sql sql-server tsql pivot


【解决方案1】:

你想要条件聚合:

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 小提琴。

【讨论】:

  • 你是对的 - 这很干净而且效果很好,谢谢。
【解决方案2】:

如果要使用非动态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

【讨论】:

    【解决方案3】:

    我建议使用条件聚合来透视您的数据集:

    • 这是一个跨数据库解决方案,因此您只需学习一次该技术,然后就可以在任何地方使用它

    • 它的性能通常至少与供应商特定的实现一样好

    • 另一个优点是您可以处理比使用 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
    

    Demo on DB Fiddle

    话题 |这个人回复 |那个人回复 |另一个人回复 |这个人评论 |那个人评论 |另一个人评论 :----------------- | :--------------- | :--------------- | :----------------- | :----------------- | :----------------- | :-------------------- 地球是平的吗? |是 |没有 |也许 |它的平|它的圆|不在乎

    【讨论】:

    • 谢谢,我也认为条件聚合是要走的路。我使用了 Yogesh 的答案,但这是一样的。非常感谢。
    • @DanielMinnaar:欢迎您。请注意,Yogesh 的答案是在我的之后发布的,并且解释较少......您为什么接受他们而不是我的任何理由?
    • 请详细说明否决票。这个答案有什么问题?
    • 我没有投反对票?我为你投票并将你的标记为答案。
    • @DanielMinnaar:当然。这个问题是针对投票者自己的......
    猜你喜欢
    • 2010-11-17
    • 2019-02-27
    • 2021-12-11
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 2014-12-30
    相关资源
    最近更新 更多