滞后函数查找缺少先前记录的先前记录值
Lag function to find previous record value with missing previous record
我需要获取之前的行或滞后记录,其中缺少一些之前的 ID。
数据库:Oracle 12c
示例数据:
BRANCH
PERIOD
QTY
105
319
17
105
320
20
105
321
32
105
322
61
107
319
17
107
321
18
107
322
16
108
319
21
108
322
27
我想要以下格式的结果:
如果您看到分支 107:缺少句点 319,对于分支 108:缺少 320,321。因此,如果以前的记录丢失,则 prev_period_<>_Qty 列应为 0。
你能帮忙实现这个目标吗?
BRANCH
PERIOD
QTY
PREV_PERIOD_1_QTY
PREV_PERIOD_2_QTY
PREV_PERIOD_3_QTY
105
319
17
0
0
0
105
320
20
17
0
0
105
321
32
20
17
0
105
322
61
32
20
17
107
319
17
0
0
0
107
321
18
0
17
0
107
322
16
18
0
17
108
319
21
0
0
0
108
322
27
0
0
21
从 Oracle 12 开始,您可以使用 MATCH_RECOGNIZE
进行 row-by-row 处理:
SELECT branch,
period,
qty,
COALESCE(prev_period_1_qty, 0) AS prev_period_1_qty,
COALESCE(prev_period_2_qty, 0) AS prev_period_2_qty,
COALESCE(prev_period_3_qty, 0) AS prev_period_3_qty
FROM table_name
MATCH_RECOGNIZE (
PARTITION BY branch
ORDER BY period DESC
MEASURES
curr.period AS period,
curr.qty AS qty,
prev1.qty AS prev_period_1_qty,
prev2.qty AS prev_period_2_qty,
prev3.qty AS prev_period_3_qty
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (curr prev1? prev2? prev3?)
DEFINE
prev1 AS curr.period - 1 = period,
prev2 AS curr.period - 2 = period,
prev3 AS curr.period - 3 = period
)
ORDER BY branch, period
或者,使用 LAG
:
SELECT branch,
period,
qty,
CASE
WHEN p1 = period - 1
THEN q1 ELSE 0
END AS prev_period_1_qty,
CASE
WHEN p1 = period - 2 THEN q1
WHEN p2 = period - 2 THEN q2
ELSE 0
END AS prev_period_2_qty,
CASE
WHEN p1 = period - 3 THEN q1
WHEN p2 = period - 3 THEN q2
WHEN p3 = period - 3 THEN q3
ELSE 0
END AS prev_period_3_qty
FROM (
SELECT t.*,
LAG(period, 1) OVER (PARTITION BY branch ORDER BY period) AS p1,
LAG(period, 2) OVER (PARTITION BY branch ORDER BY period) AS p2,
LAG(period, 3) OVER (PARTITION BY branch ORDER BY period) AS p3,
LAG(qty, 1, 0) OVER (PARTITION BY branch ORDER BY period) AS q1,
LAG(qty, 2, 0) OVER (PARTITION BY branch ORDER BY period) AS q2,
LAG(qty, 3, 0) OVER (PARTITION BY branch ORDER BY period) AS q3
FROM table_name t
)
其中,对于示例数据:
CREATE TABLE table_name (BRANCH, PERIOD, QTY) AS
SELECT 105, 319, 17 FROM DUAL UNION ALL
SELECT 105, 320, 20 FROM DUAL UNION ALL
SELECT 105, 321, 32 FROM DUAL UNION ALL
SELECT 105, 322, 61 FROM DUAL UNION ALL
SELECT 107, 319, 17 FROM DUAL UNION ALL
SELECT 107, 321, 18 FROM DUAL UNION ALL
SELECT 107, 322, 16 FROM DUAL UNION ALL
SELECT 108, 319, 21 FROM DUAL UNION ALL
SELECT 108, 322, 27 FROM DUAL;
双输出:
BRANCH
PERIOD
QTY
PREV_PERIOD_1_QTY
PREV_PERIOD_2_QTY
PREV_PERIOD_3_QTY
105
319
17
0
0
0
105
320
20
17
0
0
105
321
32
20
17
0
105
322
61
32
20
17
107
319
17
0
0
0
107
321
18
0
17
0
107
322
16
18
0
17
108
319
21
0
0
0
108
322
27
0
0
21
db<>fiddle here
我需要获取之前的行或滞后记录,其中缺少一些之前的 ID。
数据库:Oracle 12c
示例数据:
BRANCH | PERIOD | QTY |
---|---|---|
105 | 319 | 17 |
105 | 320 | 20 |
105 | 321 | 32 |
105 | 322 | 61 |
107 | 319 | 17 |
107 | 321 | 18 |
107 | 322 | 16 |
108 | 319 | 21 |
108 | 322 | 27 |
我想要以下格式的结果: 如果您看到分支 107:缺少句点 319,对于分支 108:缺少 320,321。因此,如果以前的记录丢失,则 prev_period_<>_Qty 列应为 0。
你能帮忙实现这个目标吗?
BRANCH | PERIOD | QTY | PREV_PERIOD_1_QTY | PREV_PERIOD_2_QTY | PREV_PERIOD_3_QTY |
---|---|---|---|---|---|
105 | 319 | 17 | 0 | 0 | 0 |
105 | 320 | 20 | 17 | 0 | 0 |
105 | 321 | 32 | 20 | 17 | 0 |
105 | 322 | 61 | 32 | 20 | 17 |
107 | 319 | 17 | 0 | 0 | 0 |
107 | 321 | 18 | 0 | 17 | 0 |
107 | 322 | 16 | 18 | 0 | 17 |
108 | 319 | 21 | 0 | 0 | 0 |
108 | 322 | 27 | 0 | 0 | 21 |
从 Oracle 12 开始,您可以使用 MATCH_RECOGNIZE
进行 row-by-row 处理:
SELECT branch,
period,
qty,
COALESCE(prev_period_1_qty, 0) AS prev_period_1_qty,
COALESCE(prev_period_2_qty, 0) AS prev_period_2_qty,
COALESCE(prev_period_3_qty, 0) AS prev_period_3_qty
FROM table_name
MATCH_RECOGNIZE (
PARTITION BY branch
ORDER BY period DESC
MEASURES
curr.period AS period,
curr.qty AS qty,
prev1.qty AS prev_period_1_qty,
prev2.qty AS prev_period_2_qty,
prev3.qty AS prev_period_3_qty
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (curr prev1? prev2? prev3?)
DEFINE
prev1 AS curr.period - 1 = period,
prev2 AS curr.period - 2 = period,
prev3 AS curr.period - 3 = period
)
ORDER BY branch, period
或者,使用 LAG
:
SELECT branch,
period,
qty,
CASE
WHEN p1 = period - 1
THEN q1 ELSE 0
END AS prev_period_1_qty,
CASE
WHEN p1 = period - 2 THEN q1
WHEN p2 = period - 2 THEN q2
ELSE 0
END AS prev_period_2_qty,
CASE
WHEN p1 = period - 3 THEN q1
WHEN p2 = period - 3 THEN q2
WHEN p3 = period - 3 THEN q3
ELSE 0
END AS prev_period_3_qty
FROM (
SELECT t.*,
LAG(period, 1) OVER (PARTITION BY branch ORDER BY period) AS p1,
LAG(period, 2) OVER (PARTITION BY branch ORDER BY period) AS p2,
LAG(period, 3) OVER (PARTITION BY branch ORDER BY period) AS p3,
LAG(qty, 1, 0) OVER (PARTITION BY branch ORDER BY period) AS q1,
LAG(qty, 2, 0) OVER (PARTITION BY branch ORDER BY period) AS q2,
LAG(qty, 3, 0) OVER (PARTITION BY branch ORDER BY period) AS q3
FROM table_name t
)
其中,对于示例数据:
CREATE TABLE table_name (BRANCH, PERIOD, QTY) AS
SELECT 105, 319, 17 FROM DUAL UNION ALL
SELECT 105, 320, 20 FROM DUAL UNION ALL
SELECT 105, 321, 32 FROM DUAL UNION ALL
SELECT 105, 322, 61 FROM DUAL UNION ALL
SELECT 107, 319, 17 FROM DUAL UNION ALL
SELECT 107, 321, 18 FROM DUAL UNION ALL
SELECT 107, 322, 16 FROM DUAL UNION ALL
SELECT 108, 319, 21 FROM DUAL UNION ALL
SELECT 108, 322, 27 FROM DUAL;
双输出:
BRANCH PERIOD QTY PREV_PERIOD_1_QTY PREV_PERIOD_2_QTY PREV_PERIOD_3_QTY 105 319 17 0 0 0 105 320 20 17 0 0 105 321 32 20 17 0 105 322 61 32 20 17 107 319 17 0 0 0 107 321 18 0 17 0 107 322 16 18 0 17 108 319 21 0 0 0 108 322 27 0 0 21
db<>fiddle here