oracle 如何通过较小的最近日期连接表

pu3pd22g  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(127)

我有两张这样的table

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中最小的最近日期?

mwg9r5ms

mwg9r5ms1#

我们可以使用简单易懂的方法:

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
;

字符串

vx6bjr1n

vx6bjr1n2#

在Oracle 12中,使用LATERAL join和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)

字符串
其输出:
| 日期_COL|最早日期|DATA_COL|
| --|--|--|
| 2015-03-24 11:30:00| 2015-03-21 11:30:00|表2_row1|
| 2016-08-03 07:15:00| 2016-08-02 07:15:00|表2_row3|
| 2016-02-29 22:30:00| 2016-02-28 22:30:00|表2_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)


其输出:
| 日期_COL|最近日期COL| DATA_COL|
| --|--|--|
| 2015-03-24 11:30:00| 2015-03-25 11:30:00|表2_row2|
| 2016-08-03 07:15:00| 2016-08-02 07:15:00|表2_row3|
| 2016-02-29 22:30:00| 2016-02-28 22:30:00|表2_row5|
fiddle

相关问题