[英]Oracle SQL - Return date range using MATCH_RECOGNIZE
I need help with one task I'm trying to finish.我需要帮助完成一项我正在努力完成的任务。 I need to join my data into the smallest possible date ranges and retrieve MIN( P_MIN ) and SUM( P_MAX ) over objects (in column ' name ') under one id .我需要将我的数据加入到尽可能小的日期范围内,并在一个id下检索对象(在“名称”列中)的 MIN( P_MIN ) 和 SUM( P_MAX )。
|ID |NAME |DATE_FROM |DATE_TO |P_MAX|P_MIN|
|---|--------|----------|----------|-----|-----|
|1 |OBJECT 1|10/11/2021|10/10/2022|150 |20 |
|1 |OBJECT 1|10/10/2022|02/02/2023|200 |40 |
|1 |OBJECT 1|02/02/2023|18/06/2027|100 |70 |
|1 |OBJECT 2|10/11/2021|01/05/2022|300 |60 |
|1 |OBJECT 2|01/05/2022|01/12/2022|50 |40 |
|1 |OBJECT 2|01/12/2022|18/06/2027|350 |40 |
For above I'd like to obtain对于以上我想获得
|ID |DATE_FROM |DATE_TO |SUM_P_MAX|P_MIN|
|---|----------|----------|---------|-----|
|1 |10/11/2021|01/05/2022|150+300 |20 |
|1 |01/05/2022|10/10/2022|50+150 |20 |
|1 |10/10/2022|01/12/2022|200+50 |40 |
|1 |01/12/2022|02/02/2023|350+200 |40 |
|1 |02/02/2023|18/06/2027|100+350 |40 |
"Tips" “尖端”
I was trying to resolve it using MATCH_RECOGNIZE but I couldn't get expected results.我试图使用 MATCH_RECOGNIZE 解决它,但我无法获得预期的结果。 I'm fixed with MATCH_RECOGNIZE but maybe there is a better way to resolve this?我已经修复了 MATCH_RECOGNIZE 但也许有更好的方法来解决这个问题?
Can anyone help?谁能帮忙?
Data:数据:
CREATE TABLE my_table (id number
,name varchar2(100)
,date_from date
,date_to date
,p_max number
,p_min number);
INSERT INTO my_table VALUES (1, 'OBJECT 1', TO_DATE('10/11/2021', 'DD/MM/YYYY'), TO_DATE('10/10/2022', 'DD/MM/YYYY'), 150, 20);
INSERT INTO my_table VALUES (1, 'OBJECT 1', TO_DATE('10/10/2022', 'DD/MM/YYYY'), TO_DATE('02/02/2023', 'DD/MM/YYYY'), 200, 40);
INSERT INTO my_table VALUES (1, 'OBJECT 1', TO_DATE('02/02/2023', 'DD/MM/YYYY'), TO_DATE('18/06/2027', 'DD/MM/YYYY'), 100, 70);
INSERT INTO my_table VALUES (1, 'OBJECT 2', TO_DATE('10/11/2021', 'DD/MM/YYYY'), TO_DATE('01/05/2022', 'DD/MM/YYYY'), 300, 60);
INSERT INTO my_table VALUES (1, 'OBJECT 2', TO_DATE('01/05/2022', 'DD/MM/YYYY'), TO_DATE('01/12/2022', 'DD/MM/YYYY'), 50, 40);
INSERT INTO my_table VALUES (1, 'OBJECT 2', TO_DATE('01/12/2022', 'DD/MM/YYYY'), TO_DATE('18/06/2027', 'DD/MM/YYYY'), 350, 40);
To be tested on more data:要在更多数据上进行测试:
with alldates(id, dat) as (
select id, date_from from my_table
union
select id, date_to from my_table
)
, allintervals(id, date_from, date_to) as (
select * from (
select id, dat as date_from, lead(dat) over (partition by id order by dat) as date_to from alldates
)
where date_to is not null
)
select inter.id, inter.date_from, inter.date_to, sum(p_max) as sum_pmax, min(p_min) as min_pmin
from allintervals inter
join my_table t on inter.id = t.id and (
inter.date_from between t.date_from and t.date_to-1
or
inter.date_from between t.date_from and t.date_to-1
)
group by inter.id, inter.date_from, inter.date_to
order by id, inter.date_from
;
1 10/11/21 01/05/22 450 20
1 01/05/22 10/10/22 200 20
1 10/10/22 01/12/22 250 40
1 01/12/22 02/02/23 550 40
1 02/02/23 18/06/27 450 40
You may use model
clause to reference values of other rows and calculate such totals.您可以使用model
子句来引用其他行的值并计算此类总计。
The idea behind this solution is to calculate new end dates for each interval (as long as each interval has no gaps a new end date is a next start date).此解决方案背后的想法是为每个间隔计算新的结束日期(只要每个间隔没有间隙,新的结束日期就是下一个开始日期)。 And then calculate total for intersection of this interval with all original intervals.然后计算此间隔与所有原始间隔的交集的总数。
select distinct date_from, to_ as date_to, sum_pmax, min_pmin from my_table model partition by (id) dimension by ( date_from, date_to ) measures ( p_min, p_max, /*New result values*/ 0 as min_pmin, 0 as sum_pmax, /*New value of date_to*/ date_from as to_, /*Auxiliary date_from to avoid cycle reference*/ date_from as dummy_nocycle ) rules update ( /*Each new interval starts an new value of date_from, so it will be reused. The end of each interval is the next date_from*/ /*Calculate new date_to as the nearest date_from of subsequent interval. Here we use a copy of date_from as a measure to avoid cyclic reference and be able to access it*/ to_[any, any] = coalesce(min(dummy_nocycle)[date_from > cv(date_from), date_to > cv(date_from)], cv(date_to)), /*Then aggregate measures: calculate total for all intervals that intersect with the current one (with new date_to)*/ sum_pmax[any, any] = sum(p_max)[date_from < to_[cv(), cv()], date_to > cv(date_from)], min_pmin[any, any] = min(p_min)[date_from < to_[cv(), cv()], date_to > cv(date_from)] ) order by 1, 2
DATE_FROM DATE_FROM | DATE_TO DATE_TO | SUM_PMAX SUM_PMAX | MIN_PMIN分钟_PMIN |
---|---|---|---|
2021-11-10 2021-11-10 | 2022-05-01 2022-05-01 | 450 450 | 20 20 |
2022-05-01 2022-05-01 | 2022-10-10 2022-10-10 | 200 200 | 20 20 |
2022-10-10 2022-10-10 | 2022-12-01 2022-12-01 | 250 250 | 40 40 |
2022-12-01 2022-12-01 | 2023-02-02 2023-02-02 | 550 550 | 40 40 |
2023-02-02 2023-02-02 | 2027-06-18 2027-06-18 | 450 450 | 40 40 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.