如果滞后中使用的列具有相同的值,则在使用滞后函数时分配相同的值
Assign same value when using lag function if column used in lag has same value
我有一个table在sql内容如下
+---+----------+----------+----------+--------+
| pk| from_d| to_d| load_date| row_num|
+---+----------+----------+----------+--------+
|111|2019-03-03|2019-03-03|2019-03-03| 1|
|111|2019-02-02|2019-02-02|2019-02-02| 2|
|111|2019-02-02|2019-02-02|2019-02-02| 2|
|111|2019-01-01|2019-01-01|2019-01-01| 3|
|222|2019-03-03|2019-03-03|2019-03-03| 1|
|222|2019-01-01|2019-01-01|2019-01-01| 2|
|333|2019-02-02|2019-02-02|2019-02-02| 1|
|333|2019-01-01|2019-01-01|2019-01-01| 2|
|444|2019-02-02|2019-02-02|2019-02-02| 1|
|555|2019-03-03|2019-03-03|2019-03-03| 1|
+---+----------+----------+----------+--------+
现在我想更新 to_d
列,其中 row_num > 1 使用如下条件
when row_num = 2 then to_d column should have row_num 1 row's from_d - 1 day
when row_num = 3 then to_d column should have row_num 2 row's from_d - 1 day
and so on
if row_num =1 then to_d should not be updated
我使用了如下的LAG
函数
select pk, from_d,
case when row_num = 1 then to_d else date_sub(lag(from_d) over (), 1) end as to_d,
row_num from table;
这给我的结果如下
output received
+---+----------+----------+-------------------+
| pk| from_d| to_d|row_number_window_0|
+---+----------+----------+-------------------+
|111|2019-03-03|2019-03-03| 1|
|111|2019-02-02|2019-03-02| 2|
|111|2019-02-02|2019-02-01| 2|
|111|2019-01-01|2019-02-01| 3|
|222|2019-03-03|2019-03-03| 1|
|222|2019-01-01|2019-03-02| 2|
|333|2019-02-02|2019-02-02| 1|
|333|2019-01-01|2019-02-01| 2|
|444|2019-02-02|2019-02-02| 1|
|555|2019-03-03|2019-03-03| 1|
+---+----------+----------+-------------------+
在上面的 PK
111
中,row_num = 2
to_d
列不同,我希望它们具有相同的值。
expected output
+---+----------+----------+-------------------+
| pk| from_d| to_d|row_number_window_0|
+---+----------+----------+-------------------+
|111|2019-03-03|2019-03-03| 1|
|111|2019-02-02|2019-03-02| 2|
|111|2019-02-02|2019-03-02| 2|
|111|2019-01-01|2019-02-01| 3|
|222|2019-03-03|2019-03-03| 1|
|222|2019-01-01|2019-03-02| 2|
|333|2019-02-02|2019-02-02| 1|
|333|2019-01-01|2019-02-01| 2|
|444|2019-02-02|2019-02-02| 1|
|555|2019-03-03|2019-03-03| 1|
+---+----------+----------+-------------------+
我怎样才能做到这一点
Edit
select pk, from_d,
case when row_num = 1 then to_d else date_sub(lag(from_d) over ( order by from_d), 1) end as to_d,
row_num from table;
即使在 lag
中使用 order by
我仍然得到相同的结果
对于每个 pk,构建一个 map<row_num, from_date>
。然后您可以使用地图查找 row_num-1
from_date 并减去 1 天。
演示:
with mytable as (--test dataset. Use your table instead of this
select stack(10,
111,'2019-03-03','2019-03-03','2019-03-03',1,
111,'2019-02-02','2019-02-02','2019-02-02',2,
111,'2019-02-02','2019-02-02','2019-02-02',2,
111,'2019-01-01','2019-01-01','2019-01-01',3,
222,'2019-03-03','2019-03-03','2019-03-03',1,
222,'2019-01-01','2019-01-01','2019-01-01',2,
333,'2019-02-02','2019-02-02','2019-02-02',1,
333,'2019-01-01','2019-01-01','2019-01-01',2,
444,'2019-02-02','2019-02-02','2019-02-02',1,
555,'2019-03-03','2019-03-03','2019-03-03',1
) as (pk,from_d,to_d,load_date,row_num)
)
select pk, from_d,
case when row_num>1 then date_sub(row_num_from_d_map[row_num-1],1) else to_d end to_d,
row_num
from
(
SELECT pk,from_d, to_d, row_num,
--for each pk build a map<row_num, from_date>
str_to_map(concat_ws(',',collect_set(concat(row_num,':', from_d)) over(partition by pk))) row_num_from_d_map
FROM mytable
)s
order by pk, row_num --need this to have resultset in the same order for easy result check, remove for better performance
;
结果:
pk from_d to_d row_num
111 2019-03-03 2019-03-03 1
111 2019-02-02 2019-03-02 2
111 2019-02-02 2019-03-02 2
111 2019-01-01 2019-02-01 3
222 2019-03-03 2019-03-03 1
222 2019-01-01 2019-03-02 2
333 2019-02-02 2019-02-02 1
333 2019-01-01 2019-02-01 2
444 2019-02-02 2019-02-02 1
555 2019-03-03 2019-03-03 1
我有一个table在sql内容如下
+---+----------+----------+----------+--------+
| pk| from_d| to_d| load_date| row_num|
+---+----------+----------+----------+--------+
|111|2019-03-03|2019-03-03|2019-03-03| 1|
|111|2019-02-02|2019-02-02|2019-02-02| 2|
|111|2019-02-02|2019-02-02|2019-02-02| 2|
|111|2019-01-01|2019-01-01|2019-01-01| 3|
|222|2019-03-03|2019-03-03|2019-03-03| 1|
|222|2019-01-01|2019-01-01|2019-01-01| 2|
|333|2019-02-02|2019-02-02|2019-02-02| 1|
|333|2019-01-01|2019-01-01|2019-01-01| 2|
|444|2019-02-02|2019-02-02|2019-02-02| 1|
|555|2019-03-03|2019-03-03|2019-03-03| 1|
+---+----------+----------+----------+--------+
现在我想更新 to_d
列,其中 row_num > 1 使用如下条件
when row_num = 2 then to_d column should have row_num 1 row's from_d - 1 day
when row_num = 3 then to_d column should have row_num 2 row's from_d - 1 day
and so on
if row_num =1 then to_d should not be updated
我使用了如下的LAG
函数
select pk, from_d,
case when row_num = 1 then to_d else date_sub(lag(from_d) over (), 1) end as to_d,
row_num from table;
这给我的结果如下
output received
+---+----------+----------+-------------------+
| pk| from_d| to_d|row_number_window_0|
+---+----------+----------+-------------------+
|111|2019-03-03|2019-03-03| 1|
|111|2019-02-02|2019-03-02| 2|
|111|2019-02-02|2019-02-01| 2|
|111|2019-01-01|2019-02-01| 3|
|222|2019-03-03|2019-03-03| 1|
|222|2019-01-01|2019-03-02| 2|
|333|2019-02-02|2019-02-02| 1|
|333|2019-01-01|2019-02-01| 2|
|444|2019-02-02|2019-02-02| 1|
|555|2019-03-03|2019-03-03| 1|
+---+----------+----------+-------------------+
在上面的 PK
111
中,row_num = 2
to_d
列不同,我希望它们具有相同的值。
expected output
+---+----------+----------+-------------------+
| pk| from_d| to_d|row_number_window_0|
+---+----------+----------+-------------------+
|111|2019-03-03|2019-03-03| 1|
|111|2019-02-02|2019-03-02| 2|
|111|2019-02-02|2019-03-02| 2|
|111|2019-01-01|2019-02-01| 3|
|222|2019-03-03|2019-03-03| 1|
|222|2019-01-01|2019-03-02| 2|
|333|2019-02-02|2019-02-02| 1|
|333|2019-01-01|2019-02-01| 2|
|444|2019-02-02|2019-02-02| 1|
|555|2019-03-03|2019-03-03| 1|
+---+----------+----------+-------------------+
我怎样才能做到这一点
Edit
select pk, from_d,
case when row_num = 1 then to_d else date_sub(lag(from_d) over ( order by from_d), 1) end as to_d,
row_num from table;
即使在 lag
中使用 order by
我仍然得到相同的结果
对于每个 pk,构建一个 map<row_num, from_date>
。然后您可以使用地图查找 row_num-1
from_date 并减去 1 天。
演示:
with mytable as (--test dataset. Use your table instead of this
select stack(10,
111,'2019-03-03','2019-03-03','2019-03-03',1,
111,'2019-02-02','2019-02-02','2019-02-02',2,
111,'2019-02-02','2019-02-02','2019-02-02',2,
111,'2019-01-01','2019-01-01','2019-01-01',3,
222,'2019-03-03','2019-03-03','2019-03-03',1,
222,'2019-01-01','2019-01-01','2019-01-01',2,
333,'2019-02-02','2019-02-02','2019-02-02',1,
333,'2019-01-01','2019-01-01','2019-01-01',2,
444,'2019-02-02','2019-02-02','2019-02-02',1,
555,'2019-03-03','2019-03-03','2019-03-03',1
) as (pk,from_d,to_d,load_date,row_num)
)
select pk, from_d,
case when row_num>1 then date_sub(row_num_from_d_map[row_num-1],1) else to_d end to_d,
row_num
from
(
SELECT pk,from_d, to_d, row_num,
--for each pk build a map<row_num, from_date>
str_to_map(concat_ws(',',collect_set(concat(row_num,':', from_d)) over(partition by pk))) row_num_from_d_map
FROM mytable
)s
order by pk, row_num --need this to have resultset in the same order for easy result check, remove for better performance
;
结果:
pk from_d to_d row_num
111 2019-03-03 2019-03-03 1
111 2019-02-02 2019-03-02 2
111 2019-02-02 2019-03-02 2
111 2019-01-01 2019-02-01 3
222 2019-03-03 2019-03-03 1
222 2019-01-01 2019-03-02 2
333 2019-02-02 2019-02-02 1
333 2019-01-01 2019-02-01 2
444 2019-02-02 2019-02-02 1
555 2019-03-03 2019-03-03 1