2012-11-18 31 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'代表单个员工的单一账户,主要是因为否则单个员工的多个账户的交易将被混合在一起。 –