在 Oracle SQL 中,我有来自不同人的汽车的时间序列数据(例如行驶公里数或以升为单位使用的汽油)。一些指标按工作日报告,其他指标按月或季度报告。 对于后续计算,我想在 SQL 中选择每个人的所有后续指标行,直到出现第一个报告差距。如果没有报告差距,我想选择每个人每个指标的所有行。
Person | Indicator|Date |Prev_Date |Frequency| row_num | Status
------- | -------- | -------- |----------|---------| --------| ------
A | km |2024/04/03|2024/04/02|Daily | 1 | OK
A | km |2024/04/02|2024/04/01|Daily | 2 | OK
A | km |2024/04/01|2024/01/31|Daily | 3 | not OK
A | km |2024/01/31|2024/01/30|Daily | 4 | not OK
A | gas in l |2024/04/01|2024/01/01|Quarterly| 1 | OK
A | gas in l |2024/01/01|2023/01/01|Quarterly| 2 | not OK
A | gas in l |2023/01/01|2022/10/01|Quarterly| 3 | OK
B | km |2024/04/03|2024/04/02|Daily | 1 | OK
B | km |2024/04/02|2024/04/01|Daily | 2 | OK
B | km |2024/04/01|2024/03/31|Daily | 3 | OK
B | km |2024/03/31|None |Daily | 4 | not OK
B | gas in l |2024/04/01|2024/01/01|Quarterly| 1 | OK
B | gas in l |2024/01/01|2023/01/01|Quarterly| 2 | not OK
B | gas in l |2023/01/01|2022/10/01|Quarterly| 3 | OK
我在 SQL 中使用 LAG() 将先前观察的时间戳附加到每一行。在此基础上,我添加了一个案例结构,如果根据指标的报告频率,当前观察日期和前一个观察日期之间的时间滞后是可以的,则表示“正常”。
对于每个人和指标,我现在想要选择行,直到第一行的状态为“不正常”。应包括此内容,但不应报告为此人报告的该指标的后续行。
有什么线索可以帮助那些无知的人如何到达那里吗?
期望的输出是:
Person | Indicator|Date |Prev_Date |Frequency| row_num | Status
------- | -------- | -------- |----------|---------| --------| ------
A | km |2024/04/03|2024/04/02|Daily | 1 | OK
A | km |2024/04/02|2024/04/01|Daily | 2 | OK
A | km |2024/04/01|2024/01/31|Daily | 3 | not OK
A | gas in l |2024/04/01|2024/01/01|Quarterly| 1 | OK
A | gas in l |2024/01/01|2023/01/01|Quarterly| 2 | not OK
B | km |2024/04/03|2024/04/02|Daily | 1 | OK
B | km |2024/04/02|2024/04/01|Daily | 2 | OK
B | km |2024/04/01|2024/03/31|Daily | 3 | OK
B | km |2024/03/31|None |Daily | 4 | not OK
B | gas in l |2024/04/01|2024/01/01|Quarterly| 1 | OK
B | gas in l |2024/01/01|2023/01/01|Quarterly| 2 | not OK
从 Oracle 12 开始,您可以使用
MATCH_RECOGNIZE
进行逐行模式匹配:
SELECT person,
indicator,
dt,
prev_dt,
frequency,
row_num,
status
FROM table_name
MATCH_RECOGNIZE(
PARTITION BY person, indicator
ORDER BY dt DESC
MEASURES
NEXT(dt) AS prev_dt,
CLASSIFIER() AS status,
COUNT(*) AS row_num
ALL ROWS PER MATCH
PATTERN (^ "OK"* "not OK")
DEFINE "OK" AS CASE
WHEN Frequency = 'Daily'
THEN NEXT(dt) + INTERVAL '1' DAY
WHEN Frequency = 'Quarterly'
THEN ADD_MONTHS(NEXT(dt), 3)
END = dt
)
对于样本数据:
CREATE TABLE table_name (Person, Indicator, DT, Frequency ) AS
SELECT 'A', 'km', DATE '2024-04-03', 'Daily' FROM DUAL UNION ALL
SELECT 'A', 'km', DATE '2024-04-02', 'Daily' FROM DUAL UNION ALL
SELECT 'A', 'km', DATE '2024-04-01', 'Daily' FROM DUAL UNION ALL
SELECT 'A', 'km', DATE '2024-01-31', 'Daily' FROM DUAL UNION ALL
SELECT 'A', 'gas in l', DATE '2024-04-01', 'Quarterly' FROM DUAL UNION ALL
SELECT 'A', 'gas in l', DATE '2024-01-01', 'Quarterly' FROM DUAL UNION ALL
SELECT 'A', 'gas in l', DATE '2023-01-01', 'Quarterly' FROM DUAL UNION ALL
SELECT 'B', 'km', DATE '2024-04-03', 'Daily' FROM DUAL UNION ALL
SELECT 'B', 'km', DATE '2024-04-02', 'Daily' FROM DUAL UNION ALL
SELECT 'B', 'km', DATE '2024-04-01', 'Daily' FROM DUAL UNION ALL
SELECT 'B', 'km', DATE '2024-03-31', 'Daily' FROM DUAL UNION ALL
SELECT 'B', 'gas in l', DATE '2024-04-01', 'Quarterly' FROM DUAL UNION ALL
SELECT 'B', 'gas in l', DATE '2024-01-01', 'Quarterly' FROM DUAL UNION ALL
SELECT 'B', 'gas in l', DATE '2023-01-01', 'Quarterly' FROM DUAL;
输出:
人 | 指标 | DT | PREV_DT | 频率 | ROW_NUM | 状态 |
---|---|---|---|---|---|---|
A | l 中的气体 | 2024-04-01 00:00:00 | 2024-01-01 00:00:00 | 季刊 | 1 | 好的 |
A | l 中的气体 | 2024-01-01 00:00:00 | 2023-01-01 00:00:00 | 季刊 | 2 | 不好 |
A | 公里 | 2024-04-03 00:00:00 | 2024-04-02 00:00:00 | 每日 | 1 | 好的 |
A | 公里 | 2024-04-02 00:00:00 | 2024-04-01 00:00:00 | 每日 | 2 | 好的 |
A | 公里 | 2024-04-01 00:00:00 | 2024-01-31 00:00:00 | 每日 | 3 | 不好 |
B | l 中的气体 | 2024-04-01 00:00:00 | 2024-01-01 00:00:00 | 季刊 | 1 | 好的 |
B | l 中的气体 | 2024-01-01 00:00:00 | 2023-01-01 00:00:00 | 季刊 | 2 | 不好 |
B | 公里 | 2024-04-03 00:00:00 | 2024-04-02 00:00:00 | 每日 | 1 | 好的 |
B | 公里 | 2024-04-02 00:00:00 | 2024-04-01 00:00:00 | 每日 | 2 | 好的 |
B | 公里 | 2024-04-01 00:00:00 | 2024-03-31 00:00:00 | 每日 | 3 | 好的 |
B | 公里 | 2024-03-31 00:00:00 | 空 | 每日 | 4 | 不好 |