SQL 查询以查找给定日期之前的最后一次更改
Posted
技术标签:
【中文标题】SQL 查询以查找给定日期之前的最后一次更改【英文标题】:SQL Query to find the last change prior to a given date 【发布时间】: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 方面有点菜鸟,不太清楚在 *** 的其他地方搜索的最佳术语 :)
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')
;
【问题讨论】:
【参考方案1】:感谢https://***.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 错误消息确实给了我一些新的线索和搜索词。发现这个非常相似 - ***.com/questions/45040472/… @MartinD 。 . .错误信息是什么?有一种更有效的方法可以解决这个问题——而且是一种可扩展的方法。我不确定在这种情况下是否需要它。 第一个是“标量子查询不能有多个列,除非使用 SELECT AS STRUCT 来构建 STRUCT 值”所以我只是删除了其中一个被要求的列。然后下一个错误是“不支持引用其他表的相关子查询,除非它们可以去相关,例如通过将它们转换为有效的 JOIN”,所以我在 Correlated SubQueries 上进行了搜索并查看了一些解决方案。跨度>以上是关于SQL 查询以查找给定日期之前的最后一次更改的主要内容,如果未能解决你的问题,请参考以下文章
跟踪员工在办公室时间查询 - Oracle SQL Developer