我需要一个SQL查询来使用Windowing函数Lag和Lead来执行以下操作。
对于每个Key,我需要在最终输出中执行以下Insert和update
插入条件
1.默认情况下,LAYER_NO = 0,需要写入输出
2.如果COL1,COL2,COL3的值与其宝贵记录相对应,则该记录需要写入输出。
示例:key_1 with layer_no = 2,COL3中值从400更改为600
更新条件
1.如果COL1,COL2,COL3的值与其先前记录相比没有任何变化,但“DEPART列”中有更改,则需要在输出中更新此值。
2.即使在插入带有layer_no = 0的记录后,也应按顺序更新LAYER_NO
示例:key_1 with layer_no = 3,COL1,COL2,COL3没有任何变化,但DEPART列中的值更改为“xyz”,因此需要在输出中更新。
select * from input_table;
+-----+--------+----+----+----+------+
| KEY|LAYER_NO|COL1|COL2|COL3|DEPART|
+-----+--------+----+----+----+------+
|key_1| 0| 200| 300| 400| abc|->default write
|key_1| 1| 200| 300| 400| abc|
|key_1| 2| 200| 300| 600| abc|--->change in col3,so write
|key_1| 2| 200| 300| 600| abc|
|key_1| 3| 200| 300| 600| xyz|--->change in col4,so update
|key_2| 0| 500| 700| 900| prq|->default write
|key_2| 1| 888| 555| 900| prq|--->change in col1 & col 2,so write
|key_3| 0| 111| 222| 333| lgh|->default write
|key_3| 1| 084| 222| 333| lgh|--->change in col1,so write
|key_3| 2| 084| 222| 333| rrr|--->change in col4,so update
+-----+--------+----+----+----+------+
从input_table生成以下输出的SQL查询是什么?
预期产出:
+-----+--------+----+----+----+------+
| KEY|LAYER_NO|COl1|COl2|COl3|DEPART|
+-----+--------+----+----+----+------+
|key_1| 0| 200| 300| 400| abc|
|key_1| 1| 200| 300| 600| xyz|
|key_2| 0| 500| 700| 900| prq|
|key_2| 1| 888| 555| 900| prq|
|key_3| 0| 111| 222| 333| lgh|
|key_3| 1| 084| 222| 333| rrr|
+-----+--------+----+----+----+------+
答案 0 :(得分:1)
这可以通过首先计算更改了col1,col2或col3列的行,然后通过查找后续行的最新离开值来完成,如下所示:
WITH your_table AS (SELECT 'key_1' KEY, 0 layer_no, 200 col1, 300 col2, 400 col3, 'abc' depart FROM dual UNION ALL
SELECT 'key_1' KEY, 1 layer_no, 200 col1, 300 col2, 400 col3, 'abc' depart FROM dual UNION ALL
SELECT 'key_1' KEY, 2 layer_no, 200 col1, 300 col2, 600 col3, 'abc' depart FROM dual UNION ALL
SELECT 'key_1' KEY, 2 layer_no, 200 col1, 300 col2, 600 col3, 'abc' depart FROM dual UNION ALL
SELECT 'key_1' KEY, 3 layer_no, 200 col1, 300 col2, 600 col3, 'xyz' depart FROM dual UNION ALL
SELECT 'key_2' KEY, 0 layer_no, 500 col1, 700 col2, 900 col3, 'prq' depart FROM dual UNION ALL
SELECT 'key_2' KEY, 1 layer_no, 888 col1, 555 col2, 900 col3, 'prq' depart FROM dual UNION ALL
SELECT 'key_3' KEY, 0 layer_no, 111 col1, 222 col2, 333 col3, 'lgh' depart FROM dual UNION ALL
SELECT 'key_3' KEY, 1 layer_no, 084 col1, 222 col2, 333 col3, 'lgh' depart FROM dual UNION ALL
SELECT 'key_3' KEY, 2 layer_no, 084 col1, 222 col2, 333 col3, 'rrr' depart FROM dual),
changed_rows AS (SELECT KEY,
layer_no,
col1,
col2,
col3,
depart,
CASE WHEN LAG(col1) OVER (PARTITION BY KEY ORDER BY layer_no) = col1
AND LAG(col2) OVER (PARTITION BY KEY ORDER BY layer_no) = col2
AND LAG(col3) OVER (PARTITION BY KEY ORDER BY layer_no) = col3
THEN 0
ELSE 1
END changed_cols1_to_3
FROM your_table),
define_grps AS (SELECT KEY,
layer_no,
col1,
col2,
col3,
depart,
changed_cols1_to_3,
SUM(changed_cols1_to_3) OVER (PARTITION BY KEY ORDER BY layer_no) grp
FROM changed_rows)
SELECT KEY,
grp -1 layer_no,
col2,
col2,
col3,
MAX(depart) KEEP (dense_rank LAST ORDER BY layer_no) depart
FROM define_grps
GROUP BY KEY,
col1,
col2,
col3,
grp;
KEY LAYER_NO COL2 COL2 COL3 DEPART
----- ---------- ---------- ---------- ---------- ------
key_1 0 300 300 400 abc
key_1 1 300 300 600 xyz
key_2 0 700 700 900 prq
key_2 1 555 555 900 prq
key_3 1 222 222 333 rrr
key_3 0 222 222 333 lgh
changed_rows
子查询检查col1,col2和col3以查看它是否具有与上一行相同的值(无更改)或不相同(更改)。我们为更改的行指定值1,为未更改的行指定0。
define_grps
子查询计算出每个键的所有行的changed_cols1_to_3
列的运行总计。这具有对每组连续行进行分组的效果,其中第1列,第2列和第3列是相同的。
最后,我们可以为每个组挑选最后一行。新的layer_no只是grp数减1。