【问题标题】:Check LAG and LEAD until NULL when condition is met BigQuery满足条件时检查 LAG 和 LEAD 直到 NULL BigQuery
【发布时间】:2021-01-28 18:29:35
【问题描述】:

免责声明:如果这个问题的表达方式过于复杂,我深表歉意。我已经尽力了。 我对如何解决这个问题有一个非常粗略的想法,所以我在下面附加了代码,尽管它无助于解决我的问题。谢谢。

我有一张这样的桌子:

WITH table1 AS (

  SELECT  '2020-12-01 00:00:06 UTC' Datetime,   NULL Column1,  'A0' Column2, 'x' Column3 UNION ALL
  SELECT  '2020-12-01 00:00:16 UTC',           'A1',           'A0',         'x'  UNION ALL
  SELECT  '2020-12-01 00:00:26 UTC',           'A1',           'A1',         'y'  UNION ALL
  SELECT  '2020-12-01 00:00:36 UTC',           'A1',           'A1',         'y'  UNION ALL
  SELECT  '2020-12-01 00:00:46 UTC',           'A1',           'A2',         'z'  UNION ALL
  SELECT  '2020-12-01 00:00:56 UTC',           'A1',           'A2',         'z'  UNION ALL
  SELECT  '2020-12-01 00:00:66 UTC',           NULL,           'A2',         'z'  UNION ALL
  SELECT  '2020-12-01 00:01:06 UTC',           NULL,           'A2',         'z'   
)  

select * from table1

我想创建一个新列并将 Column3 中的每个值附加到 Column1 的整个长度,如果条件 (Column1 = Column2) 至少满足一次,则 NULLS 是边界。

详细解释: 我想首先检查条件 Column1 = Column2;如果这是真的,我想检查 Column3 中的值。就我而言,这是'y'。 满足条件时,我想做 LAG 和 LEAD 直到 Column1 中的 NULL,然后将 Column1 中 A1 的整个长度的“y”应用于新列 Column4。如果一开始不满足条件 Column1 = Column2,则 Column4 中应该有 NULL。

然后输出表将是:

我尝试使用下面的代码,但不幸的是它唯一做的就是一团糟。

select *,
case when lag(Column1) over (partition by Column1 = Column2 order by DateTime) is null
             then Column3
     when lead(Column1) over (partition by Column1 = Column2 order by DateTime) is null
             then Column3
             else NULL
        end as Column4
from XX.YY.ZZ 
order by datetime

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    你可以用几个窗口函数来解决它。

    有两件事要做:
    1- 如果第 1 列 = 第 2 列,则从第 3 列获取值(简单部分:))
    2- 找到第 1 列组(岛)

    对于第一个,很清楚我在做什么:
    IF(Column1 = Column2, Column3, NULL) Col4_temp,

    对于第二个问题, 1-我尝试在 column1 中找到更改。如果 Column1 的值与上一行不同,我将其标记为 1,否则标记为 0。

    为了能够做到这一点,首先我将前一行的值与LAG(Column1) 结合起来。如果等于 Column1 的值,则返回 0,否则返回 1。

    如果前一行为 NULL,则该比较也返回 NULL,所以我用 COALESCE 填充它并将其标记为 1。

    所有更改捕获代码都在这里:
    COALESCE(IF(Lag(Column1) over wd = Column1, 0, 1), 1) as Col1_changes

    在下一步中,我累计汇总了更改的总数。如果没有变化,则表示他们在同一个组中。
    sum(Col1_changes) over (order by Datetime) as Col1_Group

    在 Col1_Group 中,您可以看到我根据更改对 Column1 进行了分组。最后,我得到每个Col1_Group 中的最大值并将其分配给Column4。

    我希望现在很清楚 :) 如果没有,我建议您了解有关窗口函数的更多信息。

    所有代码都在这里:

    WITH t1 AS (
    
      SELECT  '2020-12-01 00:00:06 UTC' Datetime,   NULL Column1,  'A0' Column2, 'x' Column3 UNION ALL
      SELECT  '2020-12-01 00:00:16 UTC',           'A1',           'A0',         'x'  UNION ALL
      SELECT  '2020-12-01 00:00:26 UTC',           'A1',           'A1',         'y'  UNION ALL
      SELECT  '2020-12-01 00:00:36 UTC',           'A1',           'A1',         'y'  UNION ALL
      SELECT  '2020-12-01 00:00:46 UTC',           'A1',           'A2',         'z'  UNION ALL
      SELECT  '2020-12-01 00:00:56 UTC',           'A1',           'A2',         'z'  UNION ALL
      SELECT  '2020-12-01 00:00:66 UTC',           NULL,           'A2',         'z'  UNION ALL
      SELECT  '2020-12-01 00:01:06 UTC',           NULL,           'A2',         'z'   
    ),
    t2 AS
    (
        select *, 
            IF(Column1 = Column2, Column3, NULL) Col4_temp,
            COALESCE(IF(Lag(Column1) over wd = Column1, 0, 1), 1) as Col1_changes
        from t1
        window wd as (order by Datetime)
    ),
    t3 as
    (
        select *,
            sum(Col1_changes) over (order by Datetime) as Col1_Group
        from t2
    )
    select *,
        MAX(Col4_temp) over (partition by Col1_Group) as Column4
    from t3
    

    【讨论】:

    • 非常感谢!我浏览了代码,但我需要一些时间才能完全理解它:)只有一件事; Column4 的第 2 行有 NULL 而不是 y。我尝试通过更改您的查询来修复它,但没有成功。你能帮我解决一下吗?
    • 太棒了,这就是我想要的。我非常感谢整个解释。我确实从这个案例和您的解决方案中学到了很多东西。再次感谢您!:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 2019-11-10
    • 2014-10-18
    • 2021-12-24
    • 1970-01-01
    相关资源
    最近更新 更多