[英]Choose the next closest date after another in Oracle SQL
How do I select the next closest received date from table2 relative to the requested date in table 1?相对于表 1 中的请求日期,如何从表 2 中选择下一个最接近的接收日期? Included the desired result at the end.
最后包括所需的结果。 I am using Oracle SQL.
我正在使用 Oracle SQL。
Table1:
PO RequestedDate
14888 01/12/2018
14733 02/12/2018
14555 05/12/2018
Table2:
PO ReceivedDate
14888 01/11/2018
14888 01/14/2018
14733 2/11/2018
14733 2/12/2018
14555 07/23/2018
14555 09/23/2018
Expected Result:
PO RequestedDate NearestReceivedDate
14888 01/12/2018 01/14/2018
14733 02/12/2018 02/12/2018
14555 05/12/2018 07/23/2018
WITH TABLE_1(PO,REQUESTED_DATE)AS
(
SELECT 14888, TO_DATE('01/12/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14733, TO_DATE('02/12/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14555, TO_DATE('05/12/2018','MM/DD/YYYY') FROM DUAL
),
TABLE_2(PO,Received_Date) AS
(
SELECT 14888, TO_DATE('01/11/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14888, TO_DATE('01/14/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14733, TO_DATE('02/11/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14733, TO_DATE('02/12/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14555, TO_DATE('07/23/2018','MM/DD/YYYY') FROM DUAL UNION ALL
SELECT 14555, TO_DATE('09/23/2018','MM/DD/YYYY') FROM DUAL
)
SELECT T.PO,CAST(T.REQUESTED_DATE AS DATE),X.RR
FROM TABLE_1 T
CROSS APPLY
(
SELECT MIN(T2.Received_Date)RR
FROM TABLE_2 T2
WHERE T.PO=T2.PO
AND CAST(T2.Received_Date AS DATE)>=CAST(T.REQUESTED_DATE AS DATE)
)X
https://dbfiddle.uk/?rdbms=oracle_21&fiddle=81cc657918a214d0f118f870eeb67a3d https://dbfiddle.uk/?rdbms=oracle_21&fiddle=81cc657918a214d0f118f870eeb67a3d
From Oracle 12, you can use a LATERAL
join and FETCH FIRST ROW ONLY
:从 Oracle 12 开始,您可以使用
LATERAL
join 和FETCH FIRST ROW ONLY
:
SELECT *
FROM table1 t1
CROSS JOIN LATERAL (
SELECT t2.receiveddate
FROM table2 t2
WHERE t1.po = t2.po
AND t1.requesteddate <= t2.receiveddate
ORDER BY
t2.receiveddate
FETCH FIRST ROW ONLY
)
Which, for the sample data:其中,对于样本数据:
CREATE TABLE Table1 (PO, RequestedDate) AS
SELECT 14888, DATE '2018-01-12' FROM DUAL UNION ALL
SELECT 14733, DATE '2018-02-12' FROM DUAL UNION ALL
SELECT 14555, DATE '2018-05-12' FROM DUAL;
CREATE TABLE Table2 (PO, ReceivedDate) AS
SELECT 14888, DATE '2018-01-11' FROM DUAL UNION ALL
SELECT 14888, DATE '2018-01-14' FROM DUAL UNION ALL
SELECT 14733, DATE '2018-02-11' FROM DUAL UNION ALL
SELECT 14733, DATE '2018-02-12' FROM DUAL UNION ALL
SELECT 14555, DATE '2018-07-23' FROM DUAL UNION ALL
SELECT 14555, DATE '2018-09-23' FROM DUAL;
Outputs:输出:
PO 采购订单
REQUESTEDDATE 申请日期
RECEIVEDDATE 收到的日期
14888 14888
12-JAN-18 18 年 1 月 12 日
14-JAN-18 18 年 1 月 14 日
14733 14733
12-FEB-18 18 年 2 月 12 日
12-FEB-18 18 年 2 月 12 日
14555 14555
12-MAY-18 18 年 5 月 12 日
23-JUL-18 18 年 7 月 23 日
You can also use below solution for your purpose您也可以根据您的目的使用以下解决方案
select t1.*, t2.ReceivedDate
from Table1 t1, Table2 t2
WHERE t1.PO = t2.PO
AND t1.RequestedDate <= t2.ReceivedDate
AND t2.ReceivedDate = (
SELECT MIN(t3.ReceivedDate)
FROM Table2 t3
WHERE t3.PO = t1.PO
AND t1.RequestedDate <= t3.ReceivedDate
)
;
As a tricky option you may transform an input dataset to a "vertical" event-like structure, order all the dates and use match_recognize
to select the row rigth after the receiveddate
.作为一个棘手的选项,您可以将输入数据集转换为“垂直”类似事件的结构,对所有日期进行排序并使用
match_recognize
在receiveddate
之后选择行。 It doesn't require nested loops compared to the lateral join/cross apply, which significantly affects the performance in case of large dataset in Table1
, and doesn't multiply the data compared to plain join
of two tables and min
aggregation.与横向连接/交叉应用相比,它不需要嵌套循环,这会显着影响
Table1
中大型数据集的性能,并且与两个表的普通join
和min
聚合相比,不会将数据相乘。
Based on the @MT0 's data:基于@MT0的数据:
with t as ( select po, /*Prepend numeric constant for stable sort order*/ '0_REQ' as src, RequestedDate as dt from table1 union all select po, '1_RCV' as src, ReceivedDate as dt from table2 ) select /*+gather_plan_statistics*/ * from t match_recognize( partition by po /*Order by dates, then by event type*/ order by dt asc, src asc measures /*Requested date is taken from a request event*/ req.dt as RequestedDate, /*Received date is taken from a receive event*/ rcv.dt as ReceivedDate pattern (req rcv) define req as src = '0_REQ', rcv as src = '1_RCV' )
PO |采购订单 | REQUESTEDDATE |
申请日期 | RECEIVEDDATE
收到的日期 ----: |
----: | :------------ |
:------------ | :-----------
:----------- 14555 |
14555 | 12-MAY-18 |
18 年 5 月 12 日 | 23-JUL-18
18 年 7 月 23 日 14733 |
14733 | 12-FEB-18 |
18 年 2 月 12 日 | 12-FEB-18
18 年 2 月 12 日 14888 |
14888 | 12-JAN-18 |
18 年 1 月 12 日 | 14-JAN-18
18 年 1 月 14 日
And just to compare at randomly upscaled dataset: db<>fiddle只是为了比较随机放大的数据集: db<>fiddle
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.