2017-04-06 73 views
-1

我有两个表格,格式如下。Oracle加入表

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 

我要离开加入表1至表2,这样在TABLE1

每个记录
TABLE1.SMUN_FNL = TABLE2.SMUN 
AND TABLE2.BASE_YMD <= TABLE1.START_DTE 

即匹配SMUN ,它应取最近 BASE_YMD 之前 START_DTE。

表2可能有也可能没有与START_DTE之前的日期匹配的SMUN或SMUN记录。 查询应该返回与TABLE1相同数量的记录。 (TABLE1 LEFT JOIN 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 

但是它拿起07/10/2011日期都记录作为连接两条记录满足TABLE1.START_DTE <= TABLE2.BASE_YMD条件。

任何帮助表示赞赏。 谢谢

+1

您如何期待得到111 | 28/07/2015 | 16/07/2015? 2015年7月28日不是<= 16/07/2015。 –

+0

您需要解释您期望的业务逻辑将提供所需的输出 – APC

+0

Andrey Belykh - table2.base_ymd应该与table1.start_dte相同或在此之前。即base_ymd <= start_dte –

回答

1

测试:

假设

  • table1 SMUN_FNL和Start_date是UNIQUE:意味着不会重复同一个smun_FNL的日期。
  • Start_DTE和Base_YMD是日期。对于按日期排序的逻辑(减去日期并返回具有“最低”差异的那个)来工作,如果不是,则需要将它们转换为日期。

我们在这里所做的是使用窗口函数对第一个表的所谓的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版本和窗口功能已经出现了几年现在。

+0

已更新,需要包含SMUN_FNL作为窗口函数的分区逻辑的一部分,并添加示例数据以显示未发现表2匹配时发生的情况。 – xQbert

1

基于下面的评论回答“我需要table2.start_dte从table2之前最近的table2.base_ymd”和一个新的业务需求“表2可能有或没有匹配的SMUN或SMUN记录与日期之前该START_DTE查询应返回相同数量的记录为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 
+0

我需要表2中的table1.start_dte之前最近的table2.base_ymd –

+0

我更新了答案 –

+0

对内部连接持怀疑态度。我用更多的业务逻辑编辑了答案。我们不需要左连接吗? –