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

时间:2018-03-01 19:41:14

标签: sql sql-server

我有一个表层次结构:

  • GrandParentFoo,其中包含零个或多个
  • ParentFoo,其中包含零个或多个
  • ChildFoo

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

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

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

  • GrandParentFooId
  • Total ParentFoos
  • 总父母待定
  • Total ParentFoos Active
  • 已暂停的总父母数
  • Total ParentFoos已完成
  • Total ChildFoos
  • 待开始的ChildFoos总数
  • Total ChildFoos Active
  • Total ChildFoos Paused
  • Total 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写出来,还是有更简洁的方法来做到这一点?看起来某种类型的枢轴或窗口函数可以在这里工作,但我无法将其概念化。

1 个答案:

答案 0 :(得分: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)