我记得大学时代的经验法则,如果在SQL查询中放置左联接,那么该查询中的所有后续联接也必须是左联接,而不是内部联接,否则您将得到意想不到的结果。但是我不记得这些结果是什么,所以我想知道是否我可能记错了什么。任何人都可以对此表示支持或反驳吗?谢谢! :)
例如:
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id -- this inner join might be bad mojo
答案 0 :(得分:3)
不是他们一定是。它们应该是(或者最后应该是full join
)。这是一种编写查询和表达逻辑的更安全的方法。
您的查询是:
select *
from customer c left join
ledger l
on c.id = l.customerid inner join
order o
on l.orderid = o.id
left join
说“保持所有客户,即使ledger
中没有匹配的记录。第二个问:“我必须有匹配的分类帐记录。”因此,{{1 }}将第一个转换为inner join
。
由于您大概希望所有客户,无论其他两个表中是否存在匹配项,都应使用inner join
:
left join
答案 1 :(得分:2)
您正确记得其中的某些部分!
问题是,当您像这样链接联接表时
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id
JOIN是顺序执行的,因此当发生customer left join ledger
时,您要确保来自客户退货的所有已联接键(因为这是左联接!并且您将客户置于左侧)。
下一步,
以前的JOIN的结果与order
联接(使用内部联接),强制“第一个联接键”与order
的键匹配(1到1),因此您将最终仅以order
表中匹配的记录结束
坏魔力?这真的取决于您要完成的任务。
如果要保证从customers
返回的所有记录,则应保持“左连接”。
但是,您可以通过编写以下内容使它变得更直观一些(不一定是编写SQL的更好方法!)。
SELECT * FROM
(
(SELECT * from customer) c
LEFT JOIN
(SELECT * from ledger) l
ON
c.id= l.customerid
) c_and_l
INNER JOIN (OR PERHAPS LEFT JOIN)
(SELECT * FROM order) as o
ON c_and_l.orderid (better use c_and_l.id as you want to refer to customerid from customers table) = o.id
因此,现在您了解到c_and_l是首先创建的,然后按顺序联接(您可以想象它是因为2个表再次联接)