【问题标题】:Skip specific rows using LAG in sql在 sql 中使用 LAG 跳过特定行
【发布时间】:2019-11-29 15:21:30
【问题描述】:

我有一张如下所示的表格:

使用 SQL 中的 LAG 函数,我想仅对 star_date=end_date 的值执行 LAG,并获取过去的 start_date 记录,其中 start_date=end_date。 我的茶几会有一个额外的列,如下所示:

我希望我的问题很清楚,感谢任何帮助。

【问题讨论】:

    标签: sql google-bigquery lag skip


    【解决方案1】:

    您可以为这些值分配一个组并使用它:

    select t.*,
           (case when start_date = end_date
                 then lag(start_date) over (partition by (case when start_date = end_date then 1 else 0 end) order by start_date)
            end) as prev_eq_start_date
    from t;
    

    或者:

    select t.*,
           (case when start_date = end_date
                 then lag(start_date) over (partition by start_date = end_date order by start_date)
            end) as prev_eq_start_date
    from t;
    

    请注意,如果您的数据很大并且大多数行的日期不同,那么您可能会遇到资源问题。在这种情况下,一个额外的、未使用的 partition by 密钥可以提供帮助:

    select t.*,
           (case when start_date = end_date
                 then lag(start_date) over (partition by (case when start_date = end_date then 1 else 2 end), (case when start_date <> end_date then start_date end) order by start_date)
            end) as prev_eq_start_date
    from t;
    

    这对结果没有影响,但可以避免由于不同值的行太多而导致资源错误。

    【讨论】:

    • 我相信partition by (StartDate = EndDate)会报语法错误!
    • @VigneshKumarA 。 . .我已经习惯了使用countif(),以至于我忘记了 BQ 不会将布尔值视为与其他类型相同。
    • 我认为partition by (StartDate = EndDate) 会完美运行!你有没有测试并确认它没有?!
    • @MikhailBerlyant 。 . .事实上,我确实对其进行了测试,但它产生了一个错误。当然,我可能考错了。我没有按这个问题。
    • @GordonLinoff - 刚刚测试了你的原始答案(使用partition by (start_date = end_date)),它对我来说非常有效(BigQuery 标准 SQL) - 我认为它足够优雅,可以放弃它:o(显然认为我更喜欢我的回答:o)
    【解决方案2】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    SELECT *, NULL AS lag_result
    FROM `project.dataset.table` WHERE start_date != end_date
    UNION ALL
    SELECT *, LAG(start_date) OVER(ORDER BY start_date)
    FROM `project.dataset.table` WHERE start_date = end_date
    

    如果应用于您问题中的样本数据 - 结果是

    Row user_id start_date  end_date    lag_result   
    1   1       2019-01-01  2019-02-28  null     
    2   3       2019-02-27  2019-02-28  null     
    3   4       2019-08-04  2019-09-01  null     
    4   2       2019-02-01  2019-02-01  null     
    5   5       2019-08-07  2019-08-07  2019-02-01   
    6   6       2019-08-27  2019-08-27  2019-08-07     
    

    顺便说一句,如果您的 start_date 和 end_date 是 STRING 数据类型('27/02/2019')与 DATE 类型(上面查询中假设的'2019-02-27') - 你应该使用低于一个

    #standardSQL
    SELECT *, NULL AS lag_result
    FROM `project.dataset.table` WHERE start_date != end_date
    UNION ALL
    SELECT *, LAG(start_date) OVER(ORDER BY PARSE_DATE('%d/%m/%Y', start_date))
    FROM `project.dataset.table` WHERE start_date = end_date
    

    结果

    Row user_id start_date  end_date    lag_result   
    1   1   01/01/2019      28/02/2019  null     
    2   3   27/02/2019      28/02/2019  null     
    3   4   04/08/2019      01/09/2019  null     
    4   2   01/02/2019      01/02/2019  null     
    5   5   07/08/2019      07/08/2019  01/02/2019   
    6   6   27/08/2019      27/08/2019  07/08/2019  
    

    【讨论】:

      【解决方案3】:

      使用JOIN

      SQL FIDDLE

      SELECT T.*,T1.LAG_Result
      FROM TABLE T LEFT JOIN 
      (
         SELECT User_Id,LAG(start_date) OVER(ORDER BY start_date) LAG_Result
         FROM TABLE S 
         WHERE start_date = end_date
      ) T1 ON T.User_Id = T1.User_Id 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-30
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 1970-01-01
        相关资源
        最近更新 更多