Sql 有效的多群by

Sql 有效的多群by,sql,google-bigquery,Sql,Google Bigquery,我有下表: 年 周 第一天 第二天 第3天 2020 1. 步行 跳跃 游 2020 3. 步行 游 步行 2020 1. 跳跃 步行 游 您需要查找distinct事件,对表执行交叉连接,并使用条件聚合,如下所示: select t.year, t.week, e.event, count(case when t.day_1 = e.event then 1 end) as count_day_1, count(case when t.day_2 = e.even

我有下表:

年 周 第一天 第二天 第3天 2020 1. 步行 跳跃 游 2020 3. 步行 游 步行 2020 1. 跳跃 步行 游
您需要查找
distinct
事件,对表执行
交叉连接
,并使用
条件聚合
,如下所示:

select t.year, t.week, e.event, 
       count(case when t.day_1 = e.event then 1 end) as count_day_1,
       count(case when t.day_2 = e.event then 1 end) as count_day_2,
       count(case when t.day_3 = e.event then 1 end) as count_day_3 
  from your_Table t
  cross join (select distinct day_1 as event from your_table
              union all select day_2 from your_table
              union all select day_3 from your_table) e
group by t.year, t.week, e.event
演示代码是MS SQL

如果要为每个事件每周和每年生成完整的网格,则需要两个预聚合,一个用于事件,另一个用于每年和每周

比如:

这将起作用,但由于在实际聚合发生之前需要对数据进行标准化,因此效率值得怀疑


如果可能的话,我建议首先将表转换为3NF,只包含年、周、事件和日的关键列。然后可以生成一个相当有效的摘要。以提前正常化为代价。否则,查询中需要转换成本。

在BigQuery中,我将使用数组取消Pivot,然后聚合:

with t as (
       select 2020 as year, 1 as week, 'Walk' as day_1, 'Jump' as day_2, 'Swim' as day_3 union all
       select 2020, 3, 'Walk', 'Swim', 'Walk' union all
       select 2020, 1, 'Jump', 'Walk', 'Swim'
      )
select t.year, t.week, s.event,
       countif(day = 1) as day_1, countif(day = 2) as day_2, countif(day = 3) as day_3
from t cross join
     unnest([struct(t.day_1 as event, 1 as day),
             struct(t.day_2 as event, 2 as day),
             struct(t.day_3 as event, 3 as day)
            ]) s
group by t.year, t.week, s.event;
              

考虑一下这个不那么冗长的选项

select year, week, event, 
  countif(offset = 0) as day_1, 
  countif(offset = 1) as day_2, 
  countif(offset = 2) as day_3
from `project.dataset.table`,
unnest([day_1, day_2, day_3]) event with offset
where not event is null
group by year, week, event   
如果应用于问题中的样本数据,则输出为


作为一种可能的解决方案:附带条件聚合可能会有所帮助。源表中没有
事件
列,因此
交叉连接
右@astentx中应该有取消激励逻辑。已更新查询。请检查我是否已编辑,是否有效:1)e.day\u N应为t.day\u N;2) BigQuery查询
联合
并要求执行
选择distinct。。。联合所有人
。我很有趣!很难将带有insert into table变量的T-SQL内容移植到其他DBMS。您可以为此使用
with
子句,使其可移植到几乎所有SQL方言中,因此最好重写查询,使此答案在不重写代码的情况下或多或少有用
select year, week, event, 
  countif(offset = 0) as day_1, 
  countif(offset = 1) as day_2, 
  countif(offset = 2) as day_3
from `project.dataset.table`,
unnest([day_1, day_2, day_3]) event with offset
where not event is null
group by year, week, event