2012-11-18 52 views
4

我試圖獲得NOT EXISTS的掛起並遇到一些麻煩。 說我有一個2表。瞭解不存在

Employees: 
+------+------+ 
| eid | name | 
+------+------+ 
| 1 | Bob | 
| 2 | Alice| 
| 3 | Jill | 
+------+------+ 

Transactions: 
+----------+----------+----------+-----------+ 
| tid  | eid  | type  | amount | 
+----------+----------+----------+-----------+ 
| 1  | 1  | Deposit | 50  | 
| 2  | 1  | Open  | 500  | 
| 3  | 3  | Open  | 200  | 
| 4  | 2  | Withdraw | 25  | 
| 5  | 2  | Open  | 100  | 
+----------+----------+----------+-----------+ 

比方說,我想找到所有未開立任何帳戶的所有僱員的名稱,金額爲$ 250或更高。這意味着我只想要員工已經開設了一筆金額爲< 250美元的賬戶。 現在我有這樣的事情...

SELECT name FROM Employees e 
WHERE NOT EXISTS (
SELECT * FROM Transactions t 
WHERE t.type <> 'Open' AND t.amount >= 250 AND t.eid = e.eid); 

這顯然是錯誤的,我真的不明白爲什麼。

+0

「這意味着我只想要員工打開一個金額<250美元的賬戶的行。「---所以你希望用戶使用」OPEN「和」<250「進行交易? – zerkms

+0

我認爲您的問題有點含糊:「沒有開立任何金額爲250美元或更高的帳戶的員工」與「開立金額低於250美元的帳戶的員工」不同。第一種情況將包括從未開立賬戶的員工。你在追求什麼? – BellevueBob

+0

對不起。只有開設了金額低於250美元的賬戶的員工。 – user1378863

回答

1

您需要將EXISTSNOT EXISTS結合起來,因爲您「僅需要員工已開立帳戶金額爲< $ 250的行」:

SELECT name FROM Employees e 
WHERE EXISTS (
    SELECT 1 FROM Transactions t 
    WHERE t.amount < 250 AND t.type='Open' AND t.eid = e.eid) 
AND NOT EXISTS (
    SELECT 1 FROM Transactions t 
    WHERE t.amount >= 250 AND t.eid = e.eid); 

您需要EXISTS以確保只有員工返回時有一個開放賬戶,金額爲< 250。所述NOT EXISTS需要確保不僱員都包括具有額外的帳戶與量> = 250。

Here's a sql-fiddle demo

+0

類型是爲了確保我們只選擇一行打開新帳戶。 – user1378863

+0

@ user1378863:我已經編輯了答案,將其考慮在內。請注意,您必須在此處同時使用「EXISTS」和「NOT EXISTS」,以確保只有員工以「開放」帳戶<250返回,而不是那些也有額外高於250的額外帳戶。 –

+0

只有開戶數字被提及。在'NOT EXISTS'中你需要'AND t.type ='Open'嗎? –

0

我看到的唯一問題 - 就是你使用<>的交易類型,不=

SELECT name FROM Employees e 
WHERE NOT EXISTS (
SELECT null FROM Transactions t 
WHERE t.transaction_type = 'Open' AND t.amount >= 250 AND t.eid = e.eid); 

後您編輯您的問題的答案是:

SELECT name FROM Employees e 
WHERE EXISTS (
SELECT null FROM Transactions t 
WHERE t.transaction_type = 'Open' AND t.amount < 250 AND t.eid = e.eid); 
+0

這是因爲我試圖選擇類型爲「打開」的行。也許我對NOT EXISTS的理解不正確,但是如果我使用<>,那麼NOT EXISTS不會返回只有'Open'的行嗎? – user1378863

+0

@ user1378863:「假設我想查找所有未開立任何金額爲250美元或更高金額的僱員的姓名」---這意味着您需要'= OPEN'交易金額爲>> = 250' – zerkms

+0

你的回答確實給了我正確的結果,但我想知道如何用'NOT EXISTS'完成。 – user1378863

0

我建議使用LEFT JOIN代替選擇子。

SELECT name FROM Employees e 
LEFT JOIN Transactions t 
ON e.eid = t.eid 
WHERE t.tid IS NULL 
OR t.type <> 'Open' 
OR t.amount <= 250; 

這將加入所有的交易記錄,然後只包括其中的交易不存在的記錄,用戶有一個非開放的交易,或金額不符合reuiqred $ 250

+0

但這不是OP想要的。他想通過一個賬號(類型='打開',金額<250)來了解該員工,該賬戶**沒有額外的賬戶(賬戶> = 250)。你也會重複這些名字。 –

+0

連接不是子選擇的替代品。 –

+0

@TimSchmelter:沒有跡象表明其他賬戶是可能的。在我看來,'eid'代表單個員工的單一賬戶,主要是因爲否則單個員工的多個賬戶的交易將被混合在一起。 –