SQL-使用子查询与vs进行内部联接

SQL-使用子查询与vs进行内部联接,sql,sql-server,join,common-table-expression,Sql,Sql Server,Join,Common Table Expression,我正在练习SQL实践问题:57个使用“边做边学”方法解决的初级、中级和高级挑战。问题31是— 没有员工ID 4订单的客户 一名员工(Margaret Peackok,员工ID 4)下的订单最多。然而,有些客户从未向她下过订单。仅显示从未向她下过订单的客户 我所做的解决方案创建了一个临时表“cte”,并将其与现有表连接起来。实际上不好看或不可读- with cte as (Select Customers.CustomerID from customers where C

我正在练习SQL实践问题:57个使用“边做边学”方法解决的初级、中级和高级挑战。问题31是—

没有员工ID 4订单的客户

一名员工(Margaret Peackok,员工ID 4)下的订单最多。然而,有些客户从未向她下过订单。仅显示从未向她下过订单的客户

我所做的解决方案创建了一个临时表“cte”,并将其与现有表连接起来。实际上不好看或不可读-

with cte as
    (Select Customers.CustomerID 
    from customers
    where CustomerID not in 
        (select Orders.CustomerID from orders where orders.EmployeeID = '4'))

 select *  
 from cte left join 
    (select CustomerID from Orders where Orders.EmployeeID = '4') O
     on cte.CustomerID = O.CustomerID
我在网上找到了以下解决方案-

SELECT c.CustomerID, o.CustomerID
FROM Customers AS c
LEFT JOIN Orders AS o ON o.CustomerID = c.CustomerID AND o.EmployeeID = 4
WHERE o.CustomerID IS NULL;
哪个更好


我的问题-我什么时候可以在
连接
中使用
子句?有什么好处?连接是在where子句之前执行的吗

谢谢


Asaf

A
JOIN
条件可以包含任何布尔比较,甚至使用
的子查询存在
和相关子查询。对可以表达的内容没有限制

不过,只是一张便条<代码>=和
对性能有好处。不平等往往是绩效杀手

至于你的问题,我认为以下是对这个问题更直接的解释:

SELECT c.CustomerID
FROM Customers c
WHERE NOT EXISTS (SELECT 1
                  FROM Orders o 
                  WHERE o.CustomerID = c.CustomerID AND
                        o.EmployeeID = 4
                 );

也就是说,与employee 4一起获取所有没有订单的客户。

通常,我建议您始终选择最可读的查询版本,除非您可以使用实际数据测量性能差异。基于成本的优化人员应该选择一种执行查询的好方法,以便在这种情况下返回您想要的结果


对我来说,
JOIN
比CTE更具可读性

这是另一个解决方案

SELECT * FROM(
(SELECT Customers.CustomerID AS Customers_ID
      FROM Customers) AS P
          LEFT JOIN  
           (Select Orders.CustomerID from Orders
            where Orders.EmployeeID=4) as R
             on R.CustomerID = P.Customers_ID
              )
               WHERE R.CustomerID  IS NULL
               ORDER BY R.CustomerID DESC

非常感谢。您的解决方案是正确的,但是该书希望我从订单表中提供一列额外的客户ID。@Assaf。您可以只包含customer表中的customer id。匹配条件要求它们相同。谢谢您的回答。首先,我尝试了这种方法,但没有返回任何记录。书中说:“注意,对于外部联接,where子句上的过滤器在联接之后应用。”是的,联接在where子句之前执行。“联接是在where子句之前执行的吗?”(显然)这是一个常见问题解答。在考虑发帖之前,请总是用谷歌搜索你的错误信息或你的问题/问题/目标的许多清晰、简洁和准确的措辞,有没有你的特定字符串/名称,并阅读许多答案。如果你发布一个问题,用一句话作为标题。请参阅文本上方的投票箭头鼠标(&t)。这并不能回答所提出的问题。