【问题标题】:Calculate time diff by rows in group in SQL在 SQL 中按组中的行计算时间差异
【发布时间】:2020-05-13 20:33:29
【问题描述】:

我有一个包含用户站点访问和访问时间戳的数据集。如何按 id 对用户进行分组并计算 SQL 中用户访问之间的时间差?抱歉,对于新手问题,我是 SQL 的新手,试图构建一些报告。

我的数据集示例:

+----------+------------+---------------------+
| userID   | visitID    | vsitTS              |
+----------+------------+---------------------+
| user01   | visit01    | 2019-05-13 01:00:00 |
| user01   | visit02    | 2019-05-13 01:10:00 |
| user02   | visit01    | 2019-05-13 01:05:00 |
| user02   | visit02    | 2019-05-13 01:10:00 |
| user02   | visit03    | 2019-05-13 01:20:00 |
| user02   | visit04    | 2019-05-13 01:30:00 |
+----------+------------+---------------------+

我需要这样的结果:

+----------+------------+---------------+
| userID   | visitID    | time_dif_sec  |
+----------+------------+---------------+
| user01   | visit01    | 0             |
| user01   | visit02    | 10            |
| user02   | visit01    | 0             |
| user02   | visit02    | 5             |
| user02   | visit03    | 10            |
| user02   | visit04    | 10            |
+----------+------------+---------------+

【问题讨论】:

  • 我删除了不一致的数据库标签。请仅使用您真正使用的数据库进行标记。

标签: sql date google-bigquery window-functions


【解决方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
SELECT 
  userID, 
  visitID, 
  IFNULL(TIMESTAMP_DIFF(visitTS, LAG(visitTS) OVER(win), SECOND), 0) AS time_diff_sec, 
  IFNULL(TIMESTAMP_DIFF(visitTS, LAG(visitTS) OVER(win), MINUTE), 0) AS time_diff_min 
FROM `project.dataset.table`
WINDOW win AS (PARTITION BY userid ORDER BY visitTS)   

如果应用到您的问题中的样本数据,如下例所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'user01' userID, 'visit01' visitID, TIMESTAMP '2019-05-13 01:00:00' visitTS UNION ALL
  SELECT 'user01', 'visit02', '2019-05-13 01:10:00' UNION ALL
  SELECT 'user02', 'visit01', '2019-05-13 01:05:00' UNION ALL
  SELECT 'user02', 'visit02', '2019-05-13 01:10:00' UNION ALL
  SELECT 'user02', 'visit03', '2019-05-13 01:20:00' UNION ALL
  SELECT 'user02', 'visit04', '2019-05-13 01:30:00' 
)
SELECT 
  userID, 
  visitID, 
  IFNULL(TIMESTAMP_DIFF(visitTS, LAG(visitTS) OVER(win), SECOND), 0) AS time_diff_sec, 
  IFNULL(TIMESTAMP_DIFF(visitTS, LAG(visitTS) OVER(win), MINUTE), 0) AS time_diff_min 
FROM `project.dataset.table`
WINDOW win AS (PARTITION BY userid ORDER BY visitTS)   

输出是

Row userID  visitID time_diff_sec   time_diff_min    
1   user01  visit01 0               0    
2   user01  visit02 600             10   
3   user02  visit01 0               0    
4   user02  visit02 300             5    
5   user02  visit03 600             10   
6   user02  visit04 600             10   

【讨论】:

  • 完美运行,谢谢。还有一个问题,如何计算 time_diff
【解决方案2】:

您是否尝试过使用lag()?。它为您提供前一行值。
对于 Bigquery,您可以使用 UNIX_SECONDS() 将时间戳转换为秒,对于 MySQL,您可以使用 to_seconds()。

  select userid, visitid, 
  (UNIX_SECONDS(visitTS) - UNIX_SECONDS (lag(visitTS) over (partition by 
  userid order by userid, visitid))) as time_dif_sec 
  from table

【讨论】:

    【解决方案3】:

    您可以使用窗口函数lag() 获取“上一次”访问的时间戳,然后使用日期函数。

    在 MySQL 中(窗口函数仅在 8.0 版本中可用):

    select
        t.*,
        coalesce(
            to_seconds(visitTS)
            - to_seconds(lag(visiTS) over(partition by userID order by visitTS),
            0) ts_diff_seconds
    from mytable t
    

    在 BigQuery 中,您可以使用 timestamp_to_sec() 代替 to_seconds()。

    【讨论】:

      猜你喜欢
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多