代码之家  ›  专栏  ›  技术社区  ›  kee

BigQuery:如何使用上下文相同的数据折叠某些行

  •  0
  • kee  · 技术社区  · 7 年前

    此表具有以下架构:

    id int,
    state int,
    ts timestamp
    

    id:1, state:1, ts:2018-08-16 01:25:00
    id:1, state:1, ts:2018-08-16 02:15:00
    id:1, state:3, ts:2018-08-16 03:14:12
    id:1, state:1, ts:2018-08-16 04:35:01
    id:1, state:3, ts:2018-08-16 05:41:21
    id:1, state:3, ts:2018-08-16 06:44:57
    

    我想折叠前两行,只使用第一行,最后两行折叠到第一行,如下所示:

    id:1, state:1, ts:2018-08-16 01:25:00
    id:1, state:3, ts:2018-08-16 03:14:12
    id:1, state:1, ts:2018-08-16 04:35:01
    id:1, state:3, ts:2018-08-16 05:41:21
    

    简言之,我想用组中的第一行按时间顺序折叠状态为的连续行。在SQL中如何做到这一点?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Mikhail Berlyant    7 年前

    下面是BigQuery标准SQL

    #standardSQL
    SELECT * EXCEPT(first) FROM (
      SELECT *,  
        state <> IFNULL(LAG(state) OVER(PARTITION BY id ORDER BY ts), state + 1) first
      FROM `project.dataset.table`
    )
    WHERE first
    

    您可以使用问题中的虚拟数据来测试和玩上面的游戏(我添加了几行来演示与其他两个已经给出的答案的区别)

    #standardSQL
    WITH `project.dataset.table` AS (
      SELECT 1 id, 1 state, TIMESTAMP('2018-08-16 01:25:00') ts UNION ALL
      SELECT 1, 1, '2018-08-16 02:15:00' UNION ALL
      SELECT 1, 3, '2018-08-16 02:16:00' UNION ALL
      SELECT 1, 1, '2018-08-16 02:17:00' UNION ALL
      SELECT 1, 3, '2018-08-16 03:11:00' UNION ALL
      SELECT 1, 3, '2018-08-16 03:14:12' 
    )
    SELECT * EXCEPT(first) FROM (
      SELECT *,  
        state <> IFNULL(LAG(state) OVER(PARTITION BY id ORDER BY ts), state + 1) first
      FROM `project.dataset.table`
    )
    WHERE first
    -- ORDER BY id, ts
    

    Row id  state   ts   
    1   1   1       2018-08-16 01:25:00 UTC  
    2   1   3       2018-08-16 02:16:00 UTC  
    3   1   1       2018-08-16 02:17:00 UTC  
    4   1   3       2018-08-16 03:11:00 UTC    
    

    请注意:其他两个答案将给你以下(我真的怀疑是什么,你会期望)

    Row id  state   ts   
    1   1   1       2018-08-16 01:25:00 UTC  
    2   1   3       2018-08-16 02:16:00 UTC  
    
        2
  •  0
  •   Bobbylank    7 年前

    一个简单的小组也应该这么做吗?

    SELECT id, state, min(ts) ts
    FROM %YOUR_TABLE_NAME%
    GROUP BY id, state
    
        3
  •  0
  •   Sergiiko    7 年前

       #standardSql 
       SELECT id, state, ts 
        FROM (
         SELECT *, RANK() OVER(PARTITION BY id, state ORDER BY ts ASC) rank 
         FROM %YOUR_TABLE_NAME%
         )
        WHERE rank=1
    

    PARTITION BY id, state 意思是 id, state 是唯一的标识符和 ORDER BY ts ASC 意味着rank()函数将按时间戳(最早-更高)对行进行排序