根据条件合并行

时间:2020-07-22 16:50:12

标签: apache-spark-sql

是否可以使用sql查询根据Spark SQL中的条件合并行集合?

如果按顺序(purch_dt)放置的两个连续行中的line_num之间的差小于5 天,则将它们合并到1行中并输出合并后的结果该组的行和合并行的最大值应为purch_dt。我尝试使用LEAD函数,但遇到每种错误情况后都无法重置它,因此将以下行视为一个新组。我无法为每个这样的组获取最大purch_dt

输入:

orderid | line_num | purch_dt
1 | 1 | 10-02-2020
1 | 2 | 12-02-2020
1 | 3 | 14-02-2020
1 | 4 | 21-03-2020
1 | 5 | 23-03-2020

输出:

orderid | purch_dt
1 | 14-02-2020 -- 1 - 3 combined into 1 row because difference is <5 between each
1 | 23-02-2020 -- 4 - 5 combined into 1 row because difference is <5 between each

Total Output rows = 2,因为我们有2个组。

请注意,由于line_num = 3之间的差异大于5,因此将line_num 4用作集合中断。因此,它应该具有自己的合并记录集。

到目前为止,我已经掌握了下面的sql,但是我无法进行分组并创建组。

create temporary view next_dt as
select
order,
LEAD(purch_dt) over (partition by orderid order by line_num asc) AS next_purch_dt,
purch_dt
from orders;

select * 
from (
select 
order,
CASE WHEN datediff(next_purch_dt, purch_dt) < 5 OR next_purch IS NULL THEN 'Y'
ELSE 'N'
END AS flg
from 
next_dt)
WHERE flg = 'Y';

感谢您的帮助。

更新

需求略有变化:-

现在必须在连续记录的两个不同字段之间进行比较-当前记录的purch_dt和下一条记录的return_dt
另外,在输出合并的记录组时,应该在purch_dt中填充该组中line_num最少的记录的值。并且return_dt列中填充了同一组的最大line_num记录的值。

输入:

orderid | line_num | purch_dt   | return_dt
1       |    1     | 10-02-2020 | 10-02-2020 
1       |    2     | 12-02-2020 | 13-02-2020
1       |    3     | 14-02-2020 | 14-02-2020
1       |    4     | 21-03-2020 | 23-02-2020
1       |    5     | 23-03-2020 | 24-02-2020

输出:

orderid | purch_dt   | return_dt
1       | 10-02-2020 | 14-02-2020
1       | 21-03-2020 | 24-02-2020

Total Output rows = 2,因为我们有2个组。

请注意,每个输出记录都包含记录的purch_dt,该组中的最小值为line_num。并包含根据记录填充的return_dt,该记录中该组中的最大值为line_num

1 个答案:

答案 0 :(得分:0)

您几乎明白了,下面的查询对我有用,

sql("""create temporary view next_dt_orders as
       select * 
            from (
                   select 
                      orderid,line_num,purch_dt,
                      case when datediff( 
                                  (lead(purch_dt) over (partition by orderid order by line_num asc)), 
                                  purch_dt) < 5 
                                 then "N" 
                                 else "Y" 
                           end as flag
                   from 
                      orders) tab
       where
          flag='Y'""")
     
sql("select * from next_dt_orders").show()  

+-------+--------+----------+----+
|orderid|line_num|  purch_dt|flag|
+-------+--------+----------+----+
|      1|       3|2020-02-14|   Y|
|      1|       5|2020-03-23|   Y|
+-------+--------+----------+----+