【问题标题】:Longest Consecutive Days Count for BigQueryBigQuery 的最长连续天数
【发布时间】:2019-06-11 01:25:35
【问题描述】:

现在我只是汇总了用户工作了多少天。我正在尝试将此查询更改为最连续工作天数。

u123454u12

这可能与 BigQuery 语句有关吗?

编辑我是 Kind of close,有以下查询,但我的 u1 得到 3 而不是 2。

SELECT MIN(e.timestamp) as date_created, e.uid, COUNT(e.uid) + 1 AS streak
FROM OnSite e
LEFT JOIN OnSite ee 
  ON e.uid = ee.uid 
AND DATE(e.timestamp) = DATE(DATE_ADD(ee.timestamp, INTERVAL -1 DAY))
WHERE ee.uid IS NOT NULL
GROUP BY e.uid;

架构 (MySQL v5.7)

CREATE TABLE OnSite
    (`uid` varchar(55), `worksite_id`  varchar(55), `timestamp` datetime)
;

INSERT INTO OnSite
    (`uid`, `worksite_id`, `timestamp`)
VALUES
  ("u12345", "worksite_1", '2019-01-01'),
  ("u12345", "worksite_1", '2019-01-02'),
  ("u12345", "worksite_1", '2019-01-03'),
  ("u12345", "worksite_1", '2019-01-04'),
  ("u12345", "worksite_1", '2019-01-06'),
  ("u1", "worksite_1", '2019-01-01'),
  ("u1", "worksite_1", '2019-01-02'),
  ("u1", "worksite_1", '2019-01-05'),
  ("u1", "worksite_1", '2019-01-06')

;

查询 #1

SELECT    uid, COUNT(DISTINCT timestamp) Total
FROM      OnSite
GROUP BY  uid;

| uid    | Total |
| ------ | ----- |
| u1     | 4     |
| u12345 | 5     |

View on DB Fiddle

【问题讨论】:

  • 查询后可能需要处理数据。我不知道这样的查询。
  • @Cochu 我添加了一个编辑,我正在接近,但我是一个数字
  • u12345 将是 3,而不是 4,因为“2019-01-04”没有第二天
  • 看来@Simonare 证明我错了,只要您使用的是 MySQL 8
  • @bryan 如果答案并不能真正解决您的问题,您应该让问题保持开放状态,这样您就可能得到一个对您有用的解决方案(您可以只投票赞成答案)。我已在您的问题中添加了bigquery 标签,因此答案应仅限于在那里工作的代码。

标签: mysql google-bigquery gaps-and-islands


【解决方案1】:

以下是 BigQuery 标准 SQL

如果您对同一网站上用户的最大连续天数感兴趣:

#standardSQL
SELECT uid, MAX(consecuitive_days) max_consecuitive_days
FROM (
  SELECT uid, grp, COUNT(1) consecuitive_days
  FROM (
    SELECT uid, 
      COUNTIF(step > 1) OVER(PARTITION BY uid, worksite_id ORDER BY ts) grp
    FROM (
      SELECT uid, worksite_id, ts, 
        DATE_DIFF(ts, LAG(ts) OVER(PARTITION BY uid, worksite_id ORDER BY ts), DAY) step 
      FROM `project.dataset.table`
    )
  ) GROUP BY uid, grp
) GROUP BY uid  

如果工作地点无关紧要,而您只是在寻找最多连续天数:

#standardSQL
SELECT uid, MAX(consecuitive_days) max_consecuitive_days
FROM (
  SELECT uid, grp, COUNT(1) consecuitive_days
  FROM (
    SELECT uid, 
      COUNTIF(step > 1) OVER(PARTITION BY uid ORDER BY ts) grp
    FROM (
      SELECT uid, ts, 
        DATE_DIFF(ts, LAG(ts) OVER(PARTITION BY uid ORDER BY ts), DAY) step 
      FROM `project.dataset.table`
    )
  ) GROUP BY uid, grp
) GROUP BY uid  

您可以使用您的问题中的样本数据进行测试、播放上述任何操作,如下例所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'u12345' uid, 'worksite_1' worksite_id, DATE '2019-01-01' ts UNION ALL
  SELECT 'u12345', 'worksite_1', '2019-01-02' UNION ALL
  SELECT 'u12345', 'worksite_1', '2019-01-03' UNION ALL
  SELECT 'u12345', 'worksite_1', '2019-01-04' UNION ALL
  SELECT 'u12345', 'worksite_1', '2019-01-06' UNION ALL
  SELECT 'u1', 'worksite_1', '2019-01-01' UNION ALL
  SELECT 'u1', 'worksite_1', '2019-01-02' UNION ALL
  SELECT 'u1', 'worksite_1', '2019-01-05' UNION ALL
  SELECT 'u1', 'worksite_1', '2019-01-06' 
)
SELECT uid, MAX(consecuitive_days) max_consecuitive_days
FROM (
  SELECT uid, grp, COUNT(1) consecuitive_days
  FROM (
    SELECT uid, 
      COUNTIF(step > 1) OVER(PARTITION BY uid ORDER BY ts) grp
    FROM (
      SELECT uid, ts, 
        DATE_DIFF(ts, LAG(ts) OVER(PARTITION BY uid ORDER BY ts), DAY) step 
      FROM `project.dataset.table`
    )
  ) GROUP BY uid, grp
) GROUP BY uid   

结果:

Row uid     max_consecuitive_days    
1   u12345  4    
2   u1      2    

【讨论】:

  • 非常优雅的解决方案。这也改善了我的回答。
  • 谢谢米哈伊尔!这完全符合预期。我确实对users on the same worksite 位的含义有疑问。我很难理解这里发生了什么。如果我要添加FROM project.dataset.table WHERE worksite_id = 'x',它的工作方式会有所不同(这可能是专注于一个工作场所的完全错误的方式)
  • 我的意思是——你可以为每个用户寻找Longest Consecutive Days Count,无论该用户在哪个网站上工作。但另一种选择是为每个用户寻找Longest Consecutive Days Count,这些用户在那些日子里处于同一工作地点的额外条件。我不知道您的数据的性质和工作地点的含义 - 因此为您提供了两个版本的查询,用于各自的选项。希望这能回答您的后续问题:o)
【解决方案2】:

这适合你吗?

set @gr=1;
select uid, max(cnt) max_cnt from (
  select uid, grp, count(*) cnt from (
    select uid, 
      case when ifnull(DATE_ADD(oldDate, INTERVAL 1 DAY), timestamp)= timestamp then 
        @gr 
      else  
        @gr := @gr +1 
      end grp
    from
    (
        SELECT    
          uid, 
          timestamp, 
          lag(timestamp) over (partition by uid order by timestamp asc) as oldDate
        FROM      OnSite
    ) t
  )t2
  group by uid, grp
  )t3
group by uid

结果

| uid    | max_cnt |
| ------ | ------- |
| u1     | 2       |
| u12345 | 4       |

DB Fiddle

【讨论】:

  • 我认为语法有一些错误,它没有在 DB Fiddle 中为我运行
  • 我添加了我的 Db Fiddle
  • 你能检查一下链接吗?我只是在那里看到我的第一个查询
  • 是的,你的 DB Fiddle 只能按以下方式分组
  • 很棒的工作 Simonare,它按预期工作!感谢您查看这个。不幸的是,这不适用于我的 BigQuery 目的,但我从未对您说过任何事情,因此我将其标记为正确
猜你喜欢
  • 2022-07-19
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2023-03-12
相关资源
最近更新 更多