2009-08-10 171 views
2

我有兩個表:授權和結算。 '定居點'包含對授權的外鍵引用。篩選LEFT JOIN結果

結算也可以有一個狀態(錯誤,接受等)。

鑑於這樣的數據:

 
Authorizations   Settlements 
id    id | auth_id | status 
-----    --------------------------- 
1     1   1   ERROR 
2     2   1   ACCEPTED 

我想寫一個SQL查詢來發現,沒有一個公認的結算記錄所有授權。我嘗試了一個左外連接,但它返回太多行。例如:

SELECT * FROM authorizations a
LEFT OUTER JOIN settlements s ON a.id = s.auth_id
WHERE s.status is null OR s.status != 'ACCEPTED'

這樣做的問題是,它仍然會返回一個授權記錄,如果有一個以上的結算記錄,以及其中的一個被接受。或者,如果有多個ERROR記錄,授權將返回兩次。

我怎樣才能取得單一授權記錄沒有相應的結算記錄狀態爲「ACCEPTED」?是否可以使用直接SQL,還是必須在我的代碼中過濾結果?

回答

7
SELECT * 
FROM authorizations a 
WHERE NOT EXISTS 
     (
     SELECT NULL 
     FROM Settlements s 
     WHERE s.auth_id = a.id 
       AND s.status = 'ACCEPTED' 
     ) 
+0

+1打我的頭髮 – 2009-08-10 17:30:35

+0

謝謝!這工作完美。 – MikeQ 2009-08-10 18:39:16

0

根據你的榜樣,檢查的s.status被空,如果你改變連接是右連接是不必要的。

將與SQL Server 2005+或Oracle 9i中+工作:

WITH unacceptedSettlements AS (
    SELECT s.auth_id 
     FROM SETTLEMENTS s 
     WHERE s.status != 'ACCEPTED' 
    GROUP BY s.auth_id) 
SELECT t.* 
    FROM AUTHORIZATIONS t 
    JOIN unacceptedSettlements us ON us.auth_id = t.auth_id 

任何數據庫替代:

SELECT t.* 
    FROM AUTHORIZATIONS t 
    JOIN (SELECT s.auth_id 
     FROM SETTLEMENTS s 
     WHERE s.status != 'ACCEPTED' 
     GROUP BY s.auth_id) us ON us.auth_id = t.auth_id 
+0

如果'settlements'中沒有相應的記錄,那麼您的解決方案都不會返回'授權'。在'@ op'的例子中,授權'2'不會被返回。 – Quassnoi 2009-08-10 17:56:48

+0

根據OP:「我怎樣才能取得沒有相應結算記錄且狀態爲」ACCEPTED「的單一授權記錄?」沒有要求說明需要沒有任何SETTLEMENT記錄的AUTHORIZATION記錄。 – 2009-08-10 18:09:01

+0

授權'2'沒有狀態爲「ACCEPTED」的相應結算記錄。這是原始查詢中「LEFT JOIN」的全部內容。 – Quassnoi 2009-08-10 18:21:20

2

嘗試

SELECT a.* FROM authorizations a 
LEFT OUTER JOIN (SELECT S.* from settlements s1 
WHERE s1.status = 'ACCEPTED') 
ON a.id = s.auth_id 
WHERE s.auth_id is null 

此挑選出所有被接受的記錄然後採取不屬於該組的授權。