每天的 bigquery 聚合

Posted

技术标签:

【中文标题】每天的 bigquery 聚合【英文标题】:bigquery aggregate for daily basis 【发布时间】:2017-10-17 01:34:38 【问题描述】:

我在大查询(数据仓库)中有一个表:

我想得到以下结果:

这里是关于如何计算的解释:

    2017-10-01 = 100 美元是显而易见的,因为数据只有一个 2017-10-02 = $400 是第一行和第三行的总和。为什么?因为第二行和第三行有相同的发票。所以我们只使用最新的更新。 2017-10-04 = 800 美元是第 1,3 行和第 4 行的总和。为什么?这是因为我们每天只收取一张发票。第1行(T001),第3行(T002),第4行(T003) 2017-10-05 = $100 是第 1,5 行和第 6 行的总和。为什么?这是因为我们每天只收取一张发票。第 1 行 (T001)、第 5 行(T002)、第 6 行(T003)

老实说,我完全失去了如何做到这一点。我已经尝试过多次分组等等。但它们都没有按预期工作。这是我今天迄今为止的最新努力:

SELECT 
  amount,
  updatedDateOnly,
  invNo
FROM 
(
  SELECT 
    invNo,
    UpdatedDate,
    amount,
    DATE(updatedDate) as updatedDateOnly,
    row_number() OVER (PARTITION BY  invNo ORDER BY UpdatedDate DESC) AS rownum
  FROM [project:dataset.test] 
)
WHERE
  rownum = 1

只返回最后一个日期。现在,我不知道如何查询每日数据。

感谢任何专业且愿意帮助查询的人。谢谢。

更新: json 格式的数据,如果您想在 bigquery 或其他 SQL 服务器中尝试:

"UpdatedDate":"2017-10-01 01:00:00","InvNo":"T001","amount":100
"UpdatedDate":"2017-10-02 01:00:00","InvNo":"T002","amount":200
"UpdatedDate":"2017-10-02 02:00:00","InvNo":"T002","amount":300
"UpdatedDate":"2017-10-04 01:00:00","InvNo":"T003","amount":400
"UpdatedDate":"2017-10-05 01:00:00","InvNo":"T002","amount":500
"UpdatedDate":"2017-10-05 02:00:00","InvNo":"T003","amount":500

【问题讨论】:

您的求和逻辑对我来说并不完全清楚。你一般是1加N加N+1吗? 逻辑仍然完全不清楚。你至少应该解释#3和#4(就像你对#1和#2所做的那样) 好的。我明白了——我的意思是计算逻辑 基本上,我想为每个发票号计算每天的总金额。用户每天可以根据需要更新每张发票,因此我们应该只取最新的一张。 这正是我得到它的方式 - 请参阅我的答案:o) 【参考方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
WITH dates AS (
  SELECT DISTINCT DATE(UpdatedDate) UpdatedDay
  FROM `project.dataset.test`
),
qualified AS (
  SELECT DATE(UpdatedDate) UpdatedDay, InvNo, ARRAY_AGG(amount ORDER BY UpdatedDate DESC LIMIT 1)[SAFE_OFFSET(0)] amount
  FROM `project.dataset.test`
  GROUP BY UpdatedDay, InvNo
)
SELECT UpdatedDay, SUM(amount) amount
FROM (
  SELECT d.UpdatedDay UpdatedDay, InvNo, ARRAY_AGG(amount ORDER BY q.UpdatedDay DESC LIMIT 1)[SAFE_OFFSET(0)] amount
  FROM dates d
  JOIN qualified q
  ON q.UpdatedDay <= d.UpdatedDay
  GROUP BY UpdatedDay, InvNo
)
GROUP BY UpdatedDay
-- ORDER BY UpdatedDay

您可以使用以下来自您问题的虚拟数据来测试/玩这个

#standardSQL
WITH `project.dataset.test` AS (
  SELECT TIMESTAMP '2017-10-01 01:00:00' UpdatedDate, 'T001' InvNo, 100 amount UNION ALL
  SELECT TIMESTAMP '2017-10-02 01:00:00', 'T002', 200 UNION ALL
  SELECT TIMESTAMP '2017-10-02 02:00:00', 'T002', 300 UNION ALL
  SELECT TIMESTAMP '2017-10-04 01:00:00', 'T003', 400 UNION ALL
  SELECT TIMESTAMP '2017-10-05 01:00:00', 'T002', 500 UNION ALL
  SELECT TIMESTAMP '2017-10-05 02:00:00', 'T003', 500 
),
dates AS (
  SELECT DISTINCT DATE(UpdatedDate) UpdatedDay
  FROM `project.dataset.test`
),
qualified AS (
  SELECT DATE(UpdatedDate) UpdatedDay, InvNo, ARRAY_AGG(amount ORDER BY UpdatedDate DESC LIMIT 1)[SAFE_OFFSET(0)] amount
  FROM `project.dataset.test`
  GROUP BY UpdatedDay, InvNo
)
SELECT UpdatedDay, SUM(amount) amount
FROM (
  SELECT d.UpdatedDay UpdatedDay, InvNo, ARRAY_AGG(amount ORDER BY q.UpdatedDay DESC LIMIT 1)[SAFE_OFFSET(0)] amount
  FROM dates d
  JOIN qualified q
  ON q.UpdatedDay <= d.UpdatedDay
  GROUP BY UpdatedDay, InvNo
)
GROUP BY UpdatedDay
ORDER BY UpdatedDay

结果符合预期

UpdatedDay  amount   
2017-10-01   100     
2017-10-02   400     
2017-10-04   800     
2017-10-05  1100     

【讨论】:

感谢您的回答。有用。现在,我只需要将它应用到我的真实数据中。【参考方案2】:

在每个日期,您都需要每张发票的最新金额。那是相当复杂的。一种解决方案是从日期和记录的交叉连接开始。然后可以使用窗口函数来获取最近的金额:

select dte,
       sum(case when seqnum = 1 then amount else 0 end) as amount
from (select d.dte, t.*,
             row_number() over (partition by t.invNo order by t.UpdatedDate desc) as seqnum
      from (select distinct date(UpdatedDate) as dte
            from `project.dataset.test` t
           ) d join
           `project.dataset.test` t
           on date(t.UpdatedDate) <= d.dte
     ) td
group by dte;

【讨论】:

以上是关于每天的 bigquery 聚合的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery:聚合到不同的重复字段

Bigquery/标准 SQL:如何使用 sum() 聚合所有列(大约 100 列)?

Google-Bigquery:整合聚合

根据 BigQuery 重复记录中的字段计算聚合

BigQuery - 具有范围聚合的查询中的重复行

通过 BigQuery 上的更改事件聚合时间序列