2017-04-06 40 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

對內部連接持懷疑態度。我用更多的業務邏輯編輯了答案。我們不需要左連接嗎? –