遇到了编写SQL子查询的问题

huangapple go评论70阅读模式
英文:

Having trouble writing a SQL Sub-Query

问题

让我展示一下表之间的关系以及我想要找到的内容:
<br>**Users** - 与 **AccountManager** 之间是一对多关系
<br>**AccountManager** - 与 **Accounts** 之间是一对多关系
<br>**Accounts** - 与 **Transactions** 之间是一对多关系

Select * from Users U
JOIN AccountManager am on am.AccountManager Id = u.AccountManagerId
JOIN Accounts a on a.AccountManagerId = AccountManager.Id
JOIN Transactions t on t.AccountId = a.Id
WHERE COUNT(t.Id) = 0

编辑:感谢 @Shmiel 指出上面对 `Transactions` 的连接是不正确的。幸运的是,接受的答案解决了这个问题。

**Users** 与 **Variables** 之间是一对多关系

我正在尝试找到没有 `Transactions` **且** 没有 `Variables` 的 `Users`。
我正在使用 SSMS,并编写了前四个表的适当连接,并在末尾使用 `COUNT`,但我不确定如何获取那些没有 `Transactions` 的 `Users`,然后查询他们是否也没有 `Variables`,因为这是与 `Users` 的另一个连接。我相信这只是一个子查询,我漏掉了。

我愿意听取任何建议,希望我只是过于考虑了这个问题。
英文:

Let me show the relationships of the tables and what I'm trying to find:
<br>Users - one to many with AccountManager
<br>AccountsManager - one to many with Accounts
<br>Accounts - one to many with Transactions

Select * from Users U
JOIN AccountManager am on am.AccountManager Id = u.AccountManagerId
JOIN Accounts a on a.AccountManagerId = AccountManager.Id
JOIN Transactions t on t.AccountId = a.Id
WHERE COUNT(t.Id) = 0

Edit: Thanks to @Shmiel for pointing out the above join on Transactions is incorrect. Thankfully, the accepted answer clears that up.

Users one to many with Variables

I'm trying to find Users who have no Transactions AND no Variables.
I'm using SSMS and wrote the appropriate joins for the first four tables using COUNT at the end, but I'm not sure how to get those same Users who have no Transactions and then query if they also have no Variables as that's another join on Users. I believe it's just a subquery that I'm missing.

I'm open to any suggestions and hoping I'm just overthinking this one.

答案1

得分: 2

你需要使用反连接,在SQL中可以使用 NOT EXISTS 完成。

SELECT u.*
FROM Users u
WHERE NOT EXISTS (SELECT 1
    FROM AccountManager am
    JOIN Accounts a ON a.AccountManagerId = am.Id
    JOIN Transactions t ON t.AccountId = a.Id
    WHERE am.AccountManagerId = u.AccountManagerId
)
  AND NOT EXISTS (SELECT 1
    FROM Variables v
    WHERE v.UserId = u.Id
);

不要诱惑使用 NOT IN,它可能导致不正确的结果

你也可以使用 LEFT JOIN ... IS NULL 结构,但查询可能不太明显,编译器通常难以推理。

英文:

You need to use an anti-join, which in SQL is done with a NOT EXISTS.

SELECT u.*
FROM Users u
WHERE NOT EXISTS (SELECT 1
    FROM AccountManager am
    JOIN Accounts a on a.AccountManagerId = AccountManager.Id
    JOIN Transactions t on t.AccountId = a.Id
    WHERE am.AccountManagerId = u.AccountManagerId
)
  AND NOT EXISTS (SELECT 1
    FROM Variables v
    WHERE v.UserId = u.Id
);

Don't be tempted to use NOT IN, it can cause incorrect results.

You can also use a LEFT JOIN ... IS NULL construct, but the query can be non-obvious, and the compiler often finds it hard to reason about.

huangapple
  • 本文由 发表于 2023年6月15日 21:14:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76482876.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定