【问题标题】:In BigQuery, compute difference between two rows in group by在 BigQuery 中,计算分组中两行之间的差异
【发布时间】:2020-08-28 08:14:00
【问题描述】:
with
  my_stats as (
    select 24996 as competitionId, 17 as playerId, 'on' as onOff, 8 as fga, 4 as fgm, 0.50 as fgPct union all
    select 24996 as competitionId, 17 as playerId, 'off' as onOff, 5 as fga, 3 as fgm, 0.60 as fgPct union all
    select 24996 as competitionId, 24 as playerId, 'on' as onOff, 9 as fga, 6 as fgm, 0.67 as fgPct union all
    select 24996 as competitionId, 24 as playerId, 'off' as onOff, 3 as fga, 1 as fgm, 0.33 as fgPct union all
    select 24996 as competitionId, 27 as playerId, 'on' as onOff, 5 as fga, 4 as fgm, 0.8 as fgPct
  ),
  
  my_output as (
    select 24996 as competitionId, 17 as playerId, 'diff' as onOff, 3 as fga, 1 as fgm, -0.1 as fgPct union all
    select 24996 as competitionId, 24 as playerId, 'diff' as onOff, 6 as fga, 5 as fgm, 0.34 as fgPct
  )
  

select * from my_stats
select * from my_output

这里有一个简单的例子来展示我们正在努力解决的问题。我们有表my_stats,其中主键是competitionId, playerId, onOff 的组合,而onOff 列只能是“on”或“off”。对于单个competitionId, playerId then(其中有两行,一行用于“on”,一行用于“off”),我们希望从所有其他列中减去值(on - off)。

希望my_output 表清楚地说明了我们需要什么输出。在playerId = 27 的情况下,由于该播放器没有“关闭”行,因此可以简单地从输出中删除它们,因为无需进行计算。

【问题讨论】:

    标签: sql count google-bigquery sum pivot


    【解决方案1】:

    你可以做条件聚合:

    select
        competitionId,
        playerId,
        'diff' as onOff,
        sum(case when onOff = 'on' then fga   else - fga   end) fga,
        sum(case when onOff = 'on' then fgm   else - fgm   end) fga,
        sum(case when onOff = 'on' then fgpct else - fgpct end) fgpct
    from my_stats
    where onOff in ('on', 'off')
    group by competitionId, playerId
    having count(*) = 2
    

    这会按比赛和玩家对数据进行分组,然后条件 sum()s 计算每列的“开”和“关”值之间的差异。 having 子句过滤掉没有两个记录可用的组。

    【讨论】:

      【解决方案2】:

      基于自连接的另一种解决方案:

      select
          t1.competitionId,
          t1.playerId,
          'diff' as onOff,
          t1.fga - t2.fga as fga,
          t1.fgm - t2.fgm as fgm,
          t1.fgpct - t2.fgpct as fgpct
      from my_stats as t1
      join my_stats as t2
        on t1.competitionId = t2.competitionId
       and t1.playerId = t2.playerId
      where t1.onOff = 'on'
        and t2.onOff = 'off'
      

      你应该检查哪种方法更有效

      【讨论】:

        【解决方案3】:

        以下是 BigQuery 标准 SQL

        #standardSQL
        SELECT competitionId, playerId, 'diff' AS onOff,
          SUM(onOffSign * fga) AS fga,
          SUM(onOffSign * fgm) AS fgm,
          SUM(onOffSign * fgPct) AS fgPct  
        FROM my_stats, 
          UNNEST([IF(onOff = 'on', 1, -1)]) onOffSign
        GROUP BY competitionId, playerId
        HAVING COUNT(1) = 2  
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多