Google Big Query SQL-按日期获取最新的唯一值

罗宾·托潘

#EDIT-在评论之后,我改写我的问题

我有一个BigQuery表,我想用来获取我的应用程序的一些KPI。在此表中,我将每个创建或更新另存为新行,以保留更好的历史记录。所以我有几次相同的数据处于不同的状态。

表格示例

uuid  |status     |date         
––––––|–––––––––––|––––––––––      
3     |'inactive' |2018-05-12
1     |'active'   |2018-05-10
1     |'inactive' |2018-05-08
2     |'active'   |2018-05-08
3     |'active'   |2018-05-04
2     |'inactive' |2018-04-22
3     |'inactive' |2018-04-18

我们可以看到每个数据都有多个值。

我想得到什么

我想拥有当前“活动”条目的数量(因此之后必须没有具有相同uuid的“非活动”条目)。为了使所有事情复杂化,我每天都需要这个总数因此,每天都有“活动”条目的数量,包括前几天的数量。

因此,在此示例中,我应该得到以下结果:

date        | actives
____________|_________
2018-05-02  |   0
2018-05-03  |   0
2018-05-04  |   1
2018-05-05  |   1
2018-05-06  |   1
2018-05-07  |   1
2018-05-08  |   2
2018-05-09  |   2
2018-05-10  |   3
2018-05-11  |   3
2018-05-12  |   2

实际上,我已经成功地获得了一天的活跃量。但是我的问题是何时需要每天的结果。

我已经试过

我陷入了两个解决方案,每个解决方案都返回不同的错误。

第一个解决方案

WITH
  dates AS(
      SELECT GENERATE_DATE_ARRAY(
          DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), CURRENT_DATE(), INTERVAL 1 DAY)               
      arr_dates )
SELECT
  i_date date,
  (
  SELECT COUNT(uuid)
  FROM (
    SELECT
      uuid, status, date,
      RANK() OVER(PARTITION BY uuid ORDER BY date DESC) rank
    FROM users
    WHERE
      PARSE_DATE("%Y-%m-%d", FORMAT_DATETIME("%Y-%m-%d",date)) <= i_date
  )
  WHERE
    status = 'active'
    and rank = 1
    ## rank is the condition which causes the error
  ) users
FROM
  dates, UNNEST(arr_dates) i_date
ORDER BY i_date;

带有RANK()OVER的SELECT会正确地返回带有rank列的用户,该列使我可以知道每个uuid的最后一个条目。但是当我尝试此操作时,Correlated subqueries that reference other tables are not supported unless they can be de-correlated, such as by transforming them into an efficient JOIN.由于等级= 1的条件,我得到了:

第二种解决方案

WITH
  dates AS(
      SELECT GENERATE_DATE_ARRAY(
          DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), CURRENT_DATE(), INTERVAL 1 DAY)               
      arr_dates )
SELECT
  i_date date,
  (
  SELECT
    COUNT(t1.uuid)
  FROM
    users t1
  WHERE
    t1.date = (
      SELECT MAX(t2.date)
      FROM users t2
      WHERE
        t2.uuid = t1.uuid
        ## Here that's the i_date condition which causes problem 
        AND PARSE_DATE("%Y-%m-%d", FORMAT_DATETIME("%Y-%m-%d", t2.date)) <= i_date 
    )
    AND status='active' ) users
FROM
  dates,
  UNNEST(arr_dates) i_date
ORDER BY i_date;

在这里,第二个选择也正在工作,并且可以正确返回当前一天的活动用户数。但是问题是当我尝试使用i_date在多天内检索数据时。在这里我出现了一个LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.错误...

哪种解决方案更能成功?我应该改变什么?

而且,如果我存储数据的方式不好,我应该如何进行操作以保持精确的历史记录?

米哈伊尔·伯利安(Mikhail Berlyant)

以下是BigQuery标准SQL

#standardSQL
SELECT date, COUNT(DISTINCT uuid) total_active 
FROM `project.dataset.table`
WHERE status = 'active'
GROUP BY date 
-- ORDER BY date   

更新以解决您的“改写”问题:o)
下面的示例使用来自您问题的伪数据

#standardSQL
WITH `project.dataset.users` AS (
  SELECT 3 uuid, 'inactive' status, DATE '2018-05-12' date UNION ALL
  SELECT 1, 'active', '2018-05-10' UNION ALL
  SELECT 1, 'inactive', '2018-05-08' UNION ALL
  SELECT 2, 'active', '2018-05-08' UNION ALL
  SELECT 3, 'active', '2018-05-04' UNION ALL
  SELECT 2, 'inactive', '2018-04-22' UNION ALL
  SELECT 3, 'inactive', '2018-04-18' 
), dates AS (
  SELECT day FROM UNNEST((
    SELECT GENERATE_DATE_ARRAY(MIN(date), MAX(date))
    FROM `project.dataset.users`
  )) day
), active_users AS (
  SELECT uuid, status, date first, DATE_SUB(next_status.date, INTERVAL 1 DAY) last FROM (
    SELECT uuid, date, status, LEAD(STRUCT(status, date)) OVER(PARTITION BY uuid ORDER BY date ) next_status
    FROM `project.dataset.users` u
  )
  WHERE status = 'active'
)
SELECT day, COUNT(DISTINCT uuid) actives
FROM dates d JOIN active_users u
ON day BETWEEN first AND IFNULL(last, day)
GROUP BY day 
-- ORDER BY day

结果

Row day         actives  
1   2018-05-04  1    
2   2018-05-05  1    
3   2018-05-06  1    
4   2018-05-07  1    
5   2018-05-08  2    
6   2018-05-09  2    
7   2018-05-10  3    
8   2018-05-11  3    
9   2018-05-12  2    

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Google Big Query SQL-获取最新列值

从 Google Big Query 获取任何信息

如何在 Google Big Query 中用 SQL 比较两个值?

Google Firebase 和 Big Query:SQL 数组到列

在 Google Big Query 中使用 SQL Server 数据

基于会话的 Google Big Query SQL 聚合数据

如何在 Google Big Query 的 SQL 中展平表?

Google Big Query 的奇怪活动

根据 Google Big Query 中的条件选择先前的组值

如何从Airflow中的Big Query获取SQL查询的结果?

在 Big Query 中使用 SQL 将值拆分为当前日期和下一个日期

如何使用Google Big Query在GROUP_CONCAT上获取不同的值

SQL Server按日期获取最新值

Google Cloud Storage/Big Query 成本估算

熊猫数据框到Google Big Query

子查询(Big Query)中的 SQL 脚本?

更改 Google Big Query 上的数据类型:日期字段错误

如何在Google Big Query的特定范围内的多个日期进行查询

Google Big Query 查看 2 個特定日期的數據

使用旧版 SQL 在 Big Query 数据库中的多个表上按日期计算行数

Google Big Query:如何获取授权以更改数据集的授权

Google Big Query在“ ARRAY”类型的值上提供“无法访问字段”页面

无法访问类型为string_google big query的值上的字段

如何将字段中的值转换为Google Big Query中的不同字段?

您可以在 Google Big query 中使用一个查询创建多个表吗?

在選擇 Google Big Query 時將案例寫入另一個案例

Big Query SQL连接或链接管道字符串或字符串数组中的值

使用标准SQL从Big Query请求最后一小时数据

将遗留 sql 转换为标准 sql - Big Query