2016-02-12 65 views
1

我試圖找到一個解決方案,包括在我的連接中使用row_number()方法,但不知何故無法獲得所需的結果。Oracle加入條件與頂部1

我現在遇到的問題是基於這樣一個事實,即我從連接表中得到了一些記錄,這些記錄具有多個實例(1到多個),並且引起重複的條件相同,所以即使我認爲我可以在一個日期使用min()或max(),我有相同的情況下出現兩次。

除此之外,如果我有實例,我沒有「活動」記錄(XPIRDT IS NOT NULL),我需要拉期滿的記錄,所以我會用「OR」語句或在第一次連接不產生任何記錄並且有顯示之前評估值的情況條件的情況下,簡單地執行另一次連接以獲取過期記錄?

因此,這裏是我處理樣品的數據的一個實例:

SAMPLE DATA

所以上述數據樣本仍然會產生2條記錄,我可以通過評估截止日期消除一個以下, 但是會出現問題,如果所有的記錄都過期,所以不會檢索任何東西。

LEFT OUTER JOIN PARTYXREF 
     ON MBR_PERSON.NAMEID = PARTYXREF.NAMEID 
    AND PARTYXREF.REFTYPE LIKE 'COMM' 
LEFT JOIN (
       SELECT * 
       FROM ADDRDATA TMP 
       WHERE TMP.ADDRTYPE = '2' 
       AND TMP.EFFECTDT = (SELECT MAX(EFFECTDT) FROM ADDRDATA TMP2 WHERE TMP2.ADDRID = TMP.ADDRID) 
      ) MBR_ADDR 
     ON PARTYXREF.REFKEY = MBR_ADDR.ADDRID 

我也試着用我的「加盟」語句中以下,但不知何故,我不能利用內,我這裏有硬編碼值加盟鍵(REFKEY)的,所以實際上不工作,但似乎無法納入聯合聲明。

SELECT ADDR.* 
FROM (SELECT tmp.*, row_number() OVER (ORDER BY XPIRDT DESC) AS SEQNUM 
     FROM ADDRDATA tmp 
     WHERE tmp.ADDRTYPE = '2' 
      AND tmp.ADDRID = 10948448 
     ) ADDR 
WHERE SEQNUM = 1 

我在這上面浪費了一個多小時,所以我需要別人的觀點! :)

+0

錯誤地使用了'ROW_NUMBER'函數。你也應該用你的其他列對你的數據進行分區(所以'ROW_NUMBER'函數可以按你的日期對滿足一些條件的行進行排序) - 例子'ROW_NUMBER()OVER(通過ADDRID分區,EFFECTDT ORDER BY XPIRD DESC)'。最終,類似的'DENSE_RANK'就可以做到這一點。 – AndrewMcCoist

回答

1

我還不清楚哪個記錄,在你的例子中,你想要的,所以讓我給你一些選擇。

我從你的問題陳述中收集到你想要的最新生效日期。既然有關係參與,您不能使用max()(如你已經說過),以及row_number()是要走的路:

with cte as (
    select 
    addrid, effectdt, xpirdt, 
    row_number() over (partition by addrid order by effectdt desc) as rn 
    from addrdata 
) 
select 
    addrid, effectdt, xpirdt 
from cte 
where rn = 1 

接下來的部分是,你與零點失去了我......如果您的輔助排序是由過期日期和你想有一個空值王牌最晚截止日期,那麼你會在到期日前下令,把nulls first

with cte as (
    select 
    addrid, effectdt, xpirdt, 
    row_number() over 
     (partition by addrid order by effectdt desc, xpirdt nulls first) as rn 
    from addrdata 
) 
select 
    addrid, effectdt, xpirdt 
from cte 
where rn = 1 

這意味着該行是贏家:

10948448 5/14/2015 <null> 

但是,如果你想空值僅被認爲是如果沒有到期日,你可以使用nulls last(或忽略它,因爲它是默認值):

with cte as (
    select 
    addrid, effectdt, xpirdt, 
    row_number() over 
     (partition by addrid order by effectdt desc, xpirdt nulls last) as rn 
    from addrdata 
) 
select 
    addrid, effectdt, xpirdt 
from cte 
where rn = 1 

意義這傢伙得了獎:

10948448 5/14/2015 5/13/2015 

由於該使用row_number()你不會失去任何行 - 每一行保證有一個行號。只是如果存在真正的聯繫,那麼就是選擇哪一行。但是,您的空過期日期問題不應對此方法造成任何問題。

- 編輯16年2月13日 -

我覺得我開始理解你的問題,但我不是100%肯定。我已經納入你的代碼的片段用左手與我的建議加入,需要有空到期的第一次約會,這是我的下一個裂縫:

with cte as (
    select 
    addrid, effectdt, xpirdt, 
    row_number() over 
     (partition by addrid order by effectdt desc, xpirdt nulls first) as rn 
    from addrdata 
) 
select 
    cte.addrid, effectdt, xpirdt 
from 
    mbr_person mb 
    left join partyxref px on 
    mb.nameid = px.nameid and 
    px.reftype = 'COMM' 
    left join cte on 
    px.refkey = cte.addrid and 
    cte.rn = 1 

假設這不這樣做:

  1. 當你說空XPIRDT優先 - 你的意思是即使是最近的生效日期,或者它只是最近的EFFECTDT的一個決勝者?如果後者,那麼我應該工作。如果是前者,那麼我們需要在分析函數中切換按順序
  2. 我完全猜測,涉及到partyxrefmbr_person表。如果這不能削減它,可能會張貼一些示例數據和期望的輸出來包含這兩個表,或者擺弄它?
+0

非常感謝您,是的,NULL XPIRDT將優先於任何其他記錄,因爲它被認爲是「活躍」記錄,但是如果我沒有任何活動記錄,我會將已過期的記錄拉到下一個EFFECTDT。就您的建議而言,您能否使用ADDRID上的LEFT JOIN提供聲明?我試圖通過在生成記錄的子選擇內對其進行解釋來嘗試對其進行一些修改,但以某種方式,我只是不斷收回任何行,因爲我認爲行號優先於我在創建之前嘗試檢索的一組記錄行序列。 – denisb

+0

我的第二次嘗試已發佈.​​.....並且在可能發生的事件中有一些潛在的後續問題,並非100%解決了您的問題 – Hambone

+0

再次感謝!考慮到涉及的記錄數量,我實際上使用您建議的方法填充了不同地址的全局臨時文件,然後將臨時表加入到我的主要查詢中以獲取地址數據。今天早上根據給定的場景進行幾項測試,一切看起來都很完美!謝謝!! – denisb