提问人:Tom Tom 提问时间:11/16/2023 最后编辑:jarlhTom Tom 更新时间:11/17/2023 访问量:58
如何按较小的最近日期联接表
How to Join tables by smaller nearest date
问:
我有两张这样的桌子
WITH table1 AS (
SELECT TO_DATE('03/24/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col FROM DUAL UNION ALL
SELECT TO_DATE('08/03/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col FROM DUAL UNION ALL
SELECT TO_DATE('02/29/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col FROM DUAL
),
table2 AS (
SELECT TO_DATE('03/20/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row1' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('03/21/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row1' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('03/25/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row2' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('08/02/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row3' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('08/04/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row4' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('02/28/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row5' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('03/01/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row6' AS data_col FROM DUAL
)
select * from table1
如何在表2中找到较小的最近日期?
答:
0赞
Tom Tom
11/16/2023
#1
我们可以使用易于理解的方法,:ROW_NUMBER
ABS()
WITH table1 AS (
SELECT TO_DATE('03/24/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col FROM DUAL UNION ALL
SELECT TO_DATE('08/03/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col FROM DUAL UNION ALL
SELECT TO_DATE('02/29/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col FROM DUAL
),
table2 AS (
SELECT TO_DATE('03/20/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row1' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('03/21/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row1' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('03/25/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row2' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('08/02/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row3' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('08/04/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row4' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('02/28/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row5' AS data_col FROM DUAL UNION ALL
SELECT TO_DATE('03/01/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') AS date_col, 'table2_row6' AS data_col FROM DUAL
)
SELECT *
FROM (
SELECT table1.date_col,
table2.date_col AS nearest_smaller_date,
table2.data_col,
ROW_NUMBER() OVER (PARTITION BY table1.date_col ORDER BY ABS(table1.date_col - table2.date_col)) AS rn
FROM table1
JOIN table2 ON table1.date_col >= table2.date_col
)
WHERE rn = 1
;
输出:
DATE_COL | NEAREST_SMALLER_DATE | DATA_COL | 注册护士 |
---|---|---|---|
24-三月-15 11:30:00 | 21-三月-15 11:30:00 | table2_row1 | 1 |
29-二月-16 22:30:00 | 28-二月-16 22:30:00 | table2_row5 | 1 |
03-八月-16 07:15:00 | 02-八月-16 07:15:00 | table2_row3 | 1 |
3赞
MT0
11/16/2023
#2
在 Oracle 12 中,使用 join 和 :LATERAL
FETCH FIRST ROW ONLY
WITH table1 (date_col) AS (
SELECT DATE '2015-03-24' + INTERVAL '11:30:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT DATE '2016-08-03' + INTERVAL '07:15:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT DATE '2016-02-29' + INTERVAL '22:30:00' HOUR TO SECOND FROM DUAL
),
table2 (date_col, data_col) AS (
SELECT DATE '2015-03-20' + INTERVAL '11:30:00' HOUR TO SECOND, 'table2_row1' FROM DUAL UNION ALL
SELECT DATE '2015-03-21' + INTERVAL '11:30:00' HOUR TO SECOND, 'table2_row1' FROM DUAL UNION ALL
SELECT DATE '2015-03-25' + INTERVAL '11:30:00' HOUR TO SECOND, 'table2_row2' FROM DUAL UNION ALL
SELECT DATE '2016-08-02' + INTERVAL '07:15:00' HOUR TO SECOND, 'table2_row3' FROM DUAL UNION ALL
SELECT DATE '2016-08-04' + INTERVAL '07:15:00' HOUR TO SECOND, 'table2_row4' FROM DUAL UNION ALL
SELECT DATE '2016-02-28' + INTERVAL '22:30:00' HOUR TO SECOND, 'table2_row5' FROM DUAL UNION ALL
SELECT DATE '2016-03-01' + INTERVAL '22:30:00' HOUR TO SECOND, 'table2_row6' FROM DUAL
)
SELECT t1.date_col,
t2.date_col AS nearest_earlier_date_col,
t2.data_col
FROM table1 t1
LEFT OUTER JOIN LATERAL (
SELECT *
FROM table2 t2
WHERE t2.date_col < t1.date_col
ORDER BY date_col DESC
FETCH FIRST ROW ONLY
) t2
ON (1 = 1)
输出:
DATE_COL | NEAREST_EARLIER_DATE_COL | DATA_COL |
---|---|---|
2015-03-24 11:30:00 | 2015-03-21 11:30:00 | table2_row1 |
2016-08-03 07:15:00 | 2016-08-02 07:15:00 | table2_row3 |
2016-02-29 22:30:00 | 2016-02-28 22:30:00 | table2_row5 |
如果您想要最接近的日期(更早或更晚),那么:
WITH table1 (date_col) AS (
SELECT DATE '2015-03-24' + INTERVAL '11:30:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT DATE '2016-08-03' + INTERVAL '07:15:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT DATE '2016-02-29' + INTERVAL '22:30:00' HOUR TO SECOND FROM DUAL
),
table2 (date_col, data_col) AS (
SELECT DATE '2015-03-20' + INTERVAL '11:30:00' HOUR TO SECOND, 'table2_row1' FROM DUAL UNION ALL
SELECT DATE '2015-03-21' + INTERVAL '11:30:00' HOUR TO SECOND, 'table2_row1' FROM DUAL UNION ALL
SELECT DATE '2015-03-25' + INTERVAL '11:30:00' HOUR TO SECOND, 'table2_row2' FROM DUAL UNION ALL
SELECT DATE '2016-08-02' + INTERVAL '07:15:00' HOUR TO SECOND, 'table2_row3' FROM DUAL UNION ALL
SELECT DATE '2016-08-04' + INTERVAL '07:15:00' HOUR TO SECOND, 'table2_row4' FROM DUAL UNION ALL
SELECT DATE '2016-02-28' + INTERVAL '22:30:00' HOUR TO SECOND, 'table2_row5' FROM DUAL UNION ALL
SELECT DATE '2016-03-01' + INTERVAL '22:30:00' HOUR TO SECOND, 'table2_row6' FROM DUAL
)
SELECT t1.date_col,
t2.date_col AS nearest_date_col,
t2.data_col
FROM table1 t1
LEFT OUTER JOIN LATERAL (
SELECT *
FROM table2 t2
ORDER BY ABS(t1.date_col - t2.date_col) ASC
FETCH FIRST ROW ONLY
) t2
ON (1 = 1)
输出:
DATE_COL | NEAREST_DATE_COL | DATA_COL |
---|---|---|
2015-03-24 11:30:00 | 2015-03-25 11:30:00 | table2_row2 |
2016-08-03 07:15:00 | 2016-08-02 07:15:00 | table2_row3 |
2016-02-29 22:30:00 | 2016-02-28 22:30:00 | table2_row5 |
评论