我有以下格式的两张表。
TABLE1
SMUN_FNL,START_DTE
111 , 07/10/2011
111 , 28/07/2015
TABLE2
SMUN,BASE_YMD
111 ,30/09/2011
111 ,30/12/2011
111 ,16/07/2015
111 ,01/02/2014
我想将Table1连接到Table2,以便对于TABLE1中的每条记录
TABLE1.SMUN_FNL = TABLE2.SMUN
AND TABLE2.BASE_YMD <= TABLE1.START_DTE
即。为了匹配SMUN,它应该在 START_DTE之前拾取最近的 BASE_YMD 。
表2可能有也可能没有匹配的SMUN或SMUN记录,其中包含START_DTE之前的日期。 查询应返回与TABLE1相同数量的记录。 (表1左边加入TABLE2我猜)
输出
SMUN_FNL|START_DTE |BASE_YMD
111 |07/10/2011|30/09/2011
111 |28/07/2015|16/07/2015
我像这样加入
TABLE1.SMUN_FNL = TABLE2.SMUN_ID
AND TABLE1.START_DTE <= TABLE2.BASE_YMD
然而,当两条记录都满足TABLE1.START_DTE <= TABLE2.BASE_YMD
条件时,它会记录两条记录的07/10/2011日期。
任何帮助表示赞赏。 感谢
答案 0 :(得分:1)
Answering based on the comment below "I need the nearest table2.base_ymd prior to table1.start_dte from table2" and a new business requirement "Table2 may or may not have a matching SMUN, or SMUN record with date before the START_DTE. The query should return same number of records as TABLE1":
SELECT t1.SMUN_FNL,
TO_CHAR(t1.START_DTE, 'DD/MM/YYYY') AS START_DTE,
TO_CHAR(t2.BASE_YMD, 'DD/MM/YYYY') AS BASE_YMD
FROM
TABLE1 t1
LEFT OUTER JOIN
(
SELECT *
FROM
TABLE2 t2
INNER JOIN
(
SELECT t1.SMUN_FNL, t1.START_DTE, MIN(t1.START_DTE-t2.BASE_YMD) AS MIN_DIFF
FROM TABLE1 t1 INNER JOIN TABLE2 t2
ON t1.SMUN_FNL = t2.SMUN
AND t2.BASE_YMD <= t1.START_DTE
GROUP BY t1.SMUN_FNL, t1.START_DTE
) t3
ON t2.SMUN = t3.SMUN_FNL
) t2
ON t1.SMUN_FNL = t2.SMUN
AND t2.BASE_YMD <= t1.START_DTE
AND t1.START_DTE = t2.START_DTE
AND t1.START_DTE-t2.BASE_YMD = t2.MIN_DIFF
答案 1 :(得分:1)
测试:
假设
我们在这里做的是使用一个名为row_number()的窗口函数,对第一个表日期减去第二个表日期,得到一个以天为单位的数值,其中最低值是每个组中的第一行数。然后我们只保留每个分区的第一行(SMUN_FNL,Start_DTE组合)。
--test data
with table1(SMUN_FNL,START_DTE ) as (
SELECT 111, to_date('07/10/2011','dd/mm/yyyy') from dual union all
SELECT 112, to_date('07/10/2011','dd/mm/yyyy') from dual union all
SELECT 111, to_date('28/07/2015','dd/mm/yyyy') from dual),
table2 (SMUN,BASE_YMD) as (
SELECT 112 ,to_date('07/11/2011','dd/mm/yyyy') FROM DUAL UNION ALL
SELECT 111 ,to_date('30/09/2011','dd/mm/yyyy') FROM DUAL UNION ALL
SELECT 111 ,to_date('30/12/2011','dd/mm/yyyy') FROM DUAL UNION ALL
SELECT 111 ,to_date('16/07/2015','dd/mm/yyyy') FROM DUAL UNION ALL
SELECT 111 ,to_date('01/02/2014','dd/mm/yyyy') FROM DUAL),
--Begin part you need
cte as (
SELECT T1.SMUN_FNL
, T1.START_DTE
, T2.BASE_YMD
, row_number() over (PARTITION BY SMUN_FNL, Start_DTE
ORDER BY start_DTE-BASE_YMD asc) RN
FROM Table1 T1
LEFT JOIN Table2 T2
on T1.SMUN_FNL = T2.SMUN
and T1.START_DTE >= T2.BASE_YMD)
SELECT SMUN_FNL, Start_DTE, Base_YMD
FROM CTE
WHERE RN = 1
收率:
SMUN_FNL START_DTE BASE_YMD RN
111 07-OCT-11 30-SEP-11 1
111 28-JUL-15 16-JUL-15 1
112 07-OCT-11 1
外部应用连接也可以在这里完成这个技巧但是我不确定你的oracle版本和窗口函数已经存在了几年了。