应用左联接之前过滤表


79

我有2个表,我想在2个表连接在一起之前过滤1个表。

客户表:

   ╔══════════╦═══════╗
   ║ Customer ║ State ║
   ╠══════════╬═══════╣
   ║ A        ║ S     ║
   ║ B        ║ V     ║
   ║ C        ║ L     ║
   ╚══════════╩═══════╝

条目表:

   ╔══════════╦═══════╦══════════╗
   ║ Customer ║ Entry ║ Category ║
   ╠══════════╬═══════╬══════════╣
   ║ A        ║  5575 ║ D        ║
   ║ A        ║  6532 ║ C        ║
   ║ A        ║  3215 ║ D        ║
   ║ A        ║  5645 ║ M        ║
   ║ B        ║  3331 ║ A        ║
   ║ B        ║  4445 ║ D        ║
   ╚══════════╩═══════╩══════════╝

我想左联接,这样我就可以从Customer表中获取所有记录,而不管Entry表中是否有相关记录。但是我想在加入之前对条目表中的类别D进行过滤。

所需结果:

   ╔══════════╦═══════╦═══════╗
   ║ Customer ║ State ║ Entry ║
   ╠══════════╬═══════╬═══════╣
   ║ A        ║ S     ║  5575 ║
   ║ A        ║ S     ║  3215 ║
   ║ B        ║ V     ║  4445 ║
   ║ C        ║ L     ║  NULL ║
   ╚══════════╩═══════╩═══════╝

如果我要执行以下查询:

   SELECT Customer.Customer, Customer.State, Entry.Entry
   FROM Customer
   LEFT JOIN Entry
   ON Customer.Customer=Entry.Customer
   WHERE Entry.Category='D'

这将筛选出最后一条记录。

因此,我希望左侧表中的所有行都将其加入到按类别D筛选的条目表中。

感谢任何提前的帮助!


Answers:


112

您需要将WHERE过滤器移至以下JOIN条件:

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
   AND e.Category='D'

参见带有演示的SQL Fiddle


哇,您高效快捷!这可以解决问题,谢谢您的帮助!
Tom Jenkin

8
@TomJenkin谢谢,顺便说一句,您向网站发布了一个精彩的第一个问题。很多细节,等等
泰伦

谢谢-我想我会喜欢使用这个网站的,希望我有一天能像你一样做出贡献:D
Tom Jenkin

2
@bluefeet但两个执行计划都是平等的,不是吗?
Alex Zhukovskiy

1
如果where条件指向第一个表,则在联接之前对联接所依赖的表应用筛选。至少在我的一些测试中,我看到了这一点。我发布了该评论以回答亚历克斯的评论。
阿谢尔·科斯塔斯·佩纳

27

您也可以这样做:

SELECT c.Customer, c.State, e.Entry
FROM Customer AS c
LEFT JOIN (SELECT * FROM Entry WHERE Category='D') AS e
ON c.Customer=e.Customer

SQL小提琴在这里


3
@TomJenkin抱歉,您的回复很晚,我一直在远离计算机。不过出于好奇,我同时运行了这两个程序并检查了执行计划。执行计划几乎相同,但从某种程度上来说更好,这似乎是Bluefeet的版本。
Jeff Rosenberg

很好,这启发了我解决案件。
sivann '18

1

要么...

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
WHERE e.Category IS NULL or e.Category='D'

在SQL JOIN中,条件在WHERE之前执行。因此,在建议的解决方案中,将整个表连接起来并对其结果进行过滤-在处理大表时这可能会非常昂贵。像其他答案中所建议的那样,预期的过滤条件应属于JOIN条件的一部分
Omley

@Omley我认为您对SQL的工作方式感到困惑。SQL是声明性的,不是过程性的。在的话顺序查询有没有影响操作的顺序。这取决于引擎。从一个简单的EXPLAIN例子中,我们可以看到MySql在优化此查询方面实际上比Taryn的回答略胜一筹,尽管这肯定比管理要幸运,反之亦然。
cz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.