【问题标题】:SQL Query to find the last change prior to a given dateSQL 查询以查找给定日期之前的最后一次更改
【发布时间】:2021-03-16 12:24:57
【问题描述】:

我有 2 个表,一个包含产品更改信息,另一个包含测试信息,我正在尝试构建一个查询以查找测试前的最后一个产品更改信息。

例如,在下面的数据中,我想要返回的每个测试都类似于:

product_sn testtype testdate part_spec changedate
ABC0001 hot 2021-01-01 13:00:00 nylon 2021-01-01 00:00:00
ABC0001 hot 2021-01-01 16:00:00 steel 2021-01-01 15:00:00
ABC1234 hot 2021-01-01 18:00:00 steel 2021-01-01 17:00:00
ABC1234 cold 2021-01-01 18:10:00 steel 2021-01-01 17:00:00
ABC1234 mid 2021-01-01 18:20:00 steel 2021-01-01 17:00:00
ABC0001 hot 2021-01-02 09:00:00 brass 2021-01-01 20:00:00
ABC1234 cold 2021-01-01 19:00:00 steel 2021-01-01 17:00:00

我在 sql 方面有点菜鸟,不太清楚在 stackoverflow 的其他地方搜索的最佳术语 :)

CREATE OR REPLACE TABLE Scratchpad.product
    (`ID` INT64,
    `product_sn` STRING,
    `part_spec` STRING,
    `changedate` datetime
    )
;
    
INSERT INTO Scratchpad.product
    (`ID`, `product_sn`, `part_spec`, `changedate`)
VALUES
    (1, 'ABC0001', 'nylon','2021-01-01 00:00:00'),
    (2, 'ABC0001', 'steel','2021-01-01 15:00:00'),
    (3, 'ABC0001', 'brass','2021-01-01 20:00:00'),
    (4, 'ABC1234', 'steel','2021-01-01 17:00:00'),
    (5, 'ABC1234', 'nylon','2021-02-01 00:00:00')
;


CREATE OR REPLACE TABLE Scratchpad.test
    (`ID` INT64,
     `product_sn` STRING,
      `testtype` STRING,
      `testdate` datetime
    )
;
    
INSERT INTO Scratchpad.test
    (`ID`, `product_sn`, `testtype`, `testdate`)
VALUES
    (1, 'ABC0001', 'hot','2021-01-01 13:00:00'),
    (2, 'ABC0001', 'hot','2021-01-01 16:00:00'),
    (3, 'ABC1234', 'hot','2021-01-01 18:00:00'),
    (4, 'ABC1234', 'cold','2021-01-01 18:10:00'),
    (5, 'ABC1234', 'mid','2021-01-01 18:20:00'),
    (6, 'ABC0001', 'hot','2021-01-02 09:00:00'),
    (7, 'ABC1234', 'cold','2021-01-01 19:00:00')
;

【问题讨论】:

    标签: sql database datetime google-bigquery


    【解决方案1】:

    感谢https://stackoverflow.com/a/45041970/274349这里的另一个答案@

    #standardSQL
    SELECT 
      t.ID AS ID, 
      t.product_sn,
      t.testdate as date, 
      t.testtype,
    
      ARRAY_AGG(r.part_spec ORDER BY r.changedate desc LIMIT 1)[SAFE_OFFSET(0)] AS part_spec,
      ARRAY_AGG(r.changedate ORDER BY r.changedate desc LIMIT 1)[SAFE_OFFSET(0)] AS part_change
    
    FROM `Scratchpad.test` AS t
    JOIN `Scratchpad.product` AS r
    ON t.product_sn = r.product_sn 
    AND r.changedate <= t.testdate
    GROUP BY ID,product_sn, date, testtype
    

    【讨论】:

    • 。 .这基本上是我回答中的最后一个解决方案。但重要的是,这不会做LEFT JOIN,这是您问题的棘手部分。
    【解决方案2】:

    这在 BQ 中可能是一个棘手的问题。一种解决方案是:

    select t.*,
           (select as struct p.part_spec, p.change_date
            from `Scratchpad.product` p
            where p.product_sn = t.product_sn and
                  p.changedate < t.testdate
            order by p.changedate desc
            limit 1
           )
    from `Scratchpad.test` t;
    

    这可能有效,但 BigQuery 有时对左连接和子查询中的不等式很挑剔。

    更详细的方法是:

    select array_agg(t order by p.change_date desc limit 1)[ordinal(1)].*,
           array_agg(p order by p.change_date desc limit 1)[ordinal(1)].*
    from `Scratchpad.test` t left join
         `Scratchpad.product` p
         on p.product_sn = t.product_sn and
            p.changedate < t.testdate
    group by t.id;
    

    【讨论】:

    • 不太奏效,但 BQ 错误消息确实给了我一些新的线索和搜索词。发现这个非常相似 - stackoverflow.com/questions/45040472/…
    • @MartinD 。 . .错误信息是什么?有一种更有效的方法可以解决这个问题——而且是一种可扩展的方法。我不确定在这种情况下是否需要它。
    • 第一个是“标量子查询不能有多个列,除非使用 SELECT AS STRUCT 来构建 STRUCT 值”所以我只是删除了其中一个被要求的列。然后下一个错误是“不支持引用其他表的相关子查询,除非它们可以去相关,例如通过将它们转换为有效的 JOIN”,所以我在 Correlated SubQueries 上进行了搜索并查看了一些解决方案。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多