窗口函数/数据透视方式将同一列的不同值聚合到不同的列中?

问题描述 投票:0回答:1

我有一个表层次结构:

  • GrandParentFoo,零或更多
  • ParentFoo,零或更多
  • ChildFoo

ParentFooChildFoo都有一个Status列,总共有4种可能的状态:

  • 待定(1)
  • 有效(2)
  • 已暂停(3)
  • 完成(4)

我正在尝试编写一个查询,它给出了以下几行中任何特定GrandParentFoo的汇总:

  • GrandParentFooId
  • 总父母
  • 总父母待定
  • Total ParentFoos Active
  • 总父母暂停
  • 总父母已完成
  • ChildFoos总数
  • ChildFoos待定总数
  • Total ChildFoos Active
  • 总ChildFoos已暂停
  • ChildFoos总数已经完成

我开始走的路:

select
    gp.GrandParentFooId,
    count(distinct pf.ParentFooId) as TotalParentFoos,
    sum(case pf.Status 
        when 1 then 1
        else 0 end) as TotalParentFoosPending

...当我意识到这会给我一个夸大的数量,其中ChildFoo记录中存在多个ParentFoo记录。

我是否必须将其作为一系列CTE写出来,还是有更简洁的方法来做到这一点?看起来某种类型的枢轴或窗口函数在这里可以工作,但我无法概念化它。

sql sql-server
1个回答
1
投票

一个相对简单的方法使用count(distinct)的条件聚合:

select gp.GrandParentFooId,
    count(distinct pf.ParentFooId) as TotalParentFoos,
       count(distinct case when fp.status = 1 then pf.ParentFooId end) as parent_pending,
       count(distinct case when fp.status = 2 then pf.ParentFooId end) as parent_active,
       count(distinct case when fp.status = 3 then pf.ParentFooId end) as parent_paused,
       count(distinct case when fp.status = 4 then pf.ParentFooId end) as parent_completed,
       count(distinct c.ChildId) as num_children,
       count(distinct case when fp.status = 1 then c.ChildId end) as child_pending,
       count(distinct case when fp.status = 2 then c.ChildId end) as child_active,
       count(distinct case when fp.status = 3 then c.ChildId end) as child_paused,
       count(distinct case when fp.status = 4 then c.ChildId end) as child_completed
from grandparentfoo gp left join
     parentfoo p
     on gp.GrandParentFooId = p.GrandParentFooId left join
     childfoo c
     on p.ParentFooId = c.ParentFooId;

笔记:

  • 孩子们可能不需要COUNT(DISTINCT)COUNT(c.ChildId)可能就足够了。
  • 对于更大的数据,我会建议一个更复杂的查询来避免COUNT(DISTINCT)s。
© www.soinside.com 2019 - 2024. All rights reserved.