在应用左连接之前过滤表
Posted
技术标签:
【中文标题】在应用左连接之前过滤表【英文标题】:Filter Table Before Applying Left Join 【发布时间】:2013-02-11 04:36:18 【问题描述】:我有 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 ║
╚══════════╩═══════╩══════════╝
我想 Left Join,所以我从 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 过滤的条目表中。
提前感谢任何帮助!
【问题讨论】:
查看此链接 - sqlbenjamin.wordpress.com/2017/12/23/… 【参考方案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 我认为您对 SQL 的工作方式感到困惑。 SQL 是声明式,而不是过程式。查询中的单词顺序对操作顺序没有影响。这取决于发动机。我们可以从一个简单的EXPLAIN
看到,mysql 在优化这个查询方面实际上比 Taryn 的答案中的查询要好得多,尽管这肯定比管理更幸运,而相反的情况很可能适用于另一个引擎。【参考方案2】:
你也可以这样做:
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 小提琴here
【讨论】:
@TomJenkin 很抱歉回复晚了,我一直不在电脑旁。不过,出于好奇,我运行了这两个程序并检查了执行计划。执行计划几乎相同,但在某种程度上更好,它似乎是 Bluefeet 的版本。 太好了,这启发了我解决我的问题。【参考方案3】:您需要将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 with Demo
【讨论】:
哇,你又快又高效!这就是诀窍,感谢您的帮助! @TomJenkin 谢谢,顺便说一句,您在网站上发布了一个很棒的第一个问题。很多细节等等。 谢谢 - 我想我会喜欢使用这个网站,希望有一天我能像你一样做出贡献:D @bluefeet 但两个执行计划是平等的,不是吗? 如果 where 条件指向第一个表,则在加入前对加入所依赖的表应用过滤。至少在我的一些测试中我看到了这一点。我发布了该评论以回应亚历克斯的评论。以上是关于在应用左连接之前过滤表的主要内容,如果未能解决你的问题,请参考以下文章