WHERE 使用临时表



>我有三个表:客户、订单和退款。一些客户(不是全部)下了订单,对于某些订单(不是全部),有退款。

当我像这样连接三个表时(细节并不那么重要):

SELECT ...
FROM customers LEFT JOIN orders
ON customers.customer_id=orders.customer_id    
LEFT JOIN refunds
ON orders.order_id=refunds.order_id;
//WHERE order_id IS NOT NULL;// uncomment to filter out customers that have no orders

我得到一个大表格,其中列出了所有客户(即使是那些没有下任何订单并且在"order_id"列中有 NULL 的客户),以及他们的所有订单和订单的退款(即使并非所有订单都有退款):

NAME     ORDER_ID    ORDER AMOUNT   REFUND
------------------------------------------------------------
Natalie   2         12.50           NULL
Natalie   3         18.00           18.00
Brenda    4         20.00           NULL
Adam      NULL      NULL            NULL    

由于我只想查看已下订单的客户,即在这种情况下,我想从表中过滤 Adam,因此我从上面的 SQL 查询中取消注释"WHERE"行。这会产生所需的结果。我的问题是:在哪个表上执行 WHERE - 在原始"订单"表(没有 NULL order_id)上还是在作为 JOIN 结果的表上执行?显然是后者,但只是想确定一下,因为从SQL语法来看不是很明显,这是非常重要的一点。

谢谢

在这种情况下,你让SQL工作比它必须的更努力。 它正在对结果进行操作(可能是 MERGE 事件,或类似的东西)。

SQL有可能意识到你在做什么,优化计划,并为你改变一个INNER JOIN。 但我不能确定(SQL也不能 - 它可以随着时间的推移改变它的优化方式)。

如果您只想要订单所在的位置,请改用INNER JOIN。 SQL在这方面会更有效率。

SELECT ...
FROM customers
INNER JOIN orders
ON customers.customer_id=orders.customer_id    
LEFT JOIN refunds
ON orders.order_id=refunds.order_id;

您可以将左联接更改为内部联接,以消除没有任何订单的客户

SELECT ...
FROM customers INNER JOIN orders
ON customers.customer_id=orders.customer_id    
LEFT JOIN refunds
ON orders.order_id=refunds.order_id;

这是因为您使用的是 LEFT JOIN ,它将返回左侧表中的所有行,在您的情况下,这是 Customer 表,并返回右侧表中没有出现相应值的NULL

只需使用内部联接重写它,因此只会返回找到匹配数据的行。

SELECT ...
FROM customers 
INNER JOIN orders
    ON customers.customer_id=orders.customer_id    
INNER JOIN refunds
    ON orders.order_id=refunds.order_id;

最新更新