【问题标题】:SQL - Using LEAD to skip over rows with a certain conditionSQL - 使用 LEAD 跳过具有特定条件的行
【发布时间】:2019-11-14 11:16:44
【问题描述】:

在 Google BigQuery 中使用标准 SQL。

我有一张有 2 种订单类型的桌子:A 和 B。

Id | Type | OrderDate
-----------------
1  |  A   | 2019-03-01
2  |  B   | 2019-03-04
3  |  B   | 2019-03-04
4  |  A   | 2019-03-05
5  |  A   | 2019-03-06
6  |  B   | 2019-04-05

对于每个订单类型 A,我想计算出下一个订单 B 的时间,忽略所有其他订单 A。

所以在我的示例数据中,如果我想返回以下内容:

Id | Type | NextOrderBDate
--------------------------------
1  |  A   | 2019-03-04
4  |  A   | 2019-04-05
5  |  A   | 2019-04-05

通过将 A 和 B 的 2 个单独的表相互连接,我确实以极其低效的方式实现了结果 - 但数据集非常大,运行需要一个多小时。

我目前正在尝试使用这样的 LEAD 语句:

SELECT Id, Type,
    LEAD(OrderDate) OVER (PARTITION BY Id ORDER BY OrderDate)
FROM xxx

显然这里的问题是它会返回下一个日期,而不管订单类型。

我想知道这样做的关键是否是计算出每一行需要引导到下一个 B 类订单的正确偏移量,并且我正在努力在这里找到一个(干净的)解决方案。

提前致谢。

【问题讨论】:

    标签: sql lead google-bigquery


    【解决方案1】:

    @Gordon Linoff 是对的,除了小错误:应该找到下一个 B 订单与每个当前订单相关。因此,恕我直言,应适当调整查询窗口:

    with t (id, type, orderdate) as (
      select 1  ,  'A'   , date '2019-03-01' union
      select 2  ,  'B'   , date '2019-03-04' union
      select 3  ,  'B'   , date '2019-03-04' union
      select 4  ,  'A'   , date '2019-03-05' union
      select 5  ,  'A'   , date '2019-03-06' union
      select 6  ,  'B'   , date '2019-04-05'
    )
    select t.*
    from (select t.*,
                 min(case when type = 'B' then orderdate end)
                 over (order by orderdate 
                     rows between current row and unbounded following
                 ) as next_b_orderdate
          from t
         ) t
    where type = 'A';
    

    【讨论】:

      【解决方案2】:

      您可以按如下方式使用内联查询:

      select
          id,
          type,
          (
              select min(OrderDate) 
              from mytable t1 
              where t1.Type = 'B' and t1.OrderDate >= t.OrderDate
          ) NextOrderBDate
      from mytable t
      where type = 'A'
      

      Demo on DB Fiddlde

      编号 |类型 |下一个订单日期 -: | :--- | :------------- 1 |一个 | 2019-03-04 4 |一个 | 2019-04-05 5 |一个 | 2019-04-05

      【讨论】:

        【解决方案3】:

        只需使用累积最小值:

        select t.*
        from (select t.*,
                     min(case when type = 'B' then orderdate end) over (order by orderdate) as next_b_orderdate
              from t
             ) t
        where type = 'A';
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多