简体   繁体   中英

SQL - INNER JOIN with AND vs using sub-query

I'm practicing questions for the book "SQL Practice Problems: 57 beginning, intermediate, and advanced challenges for you to solve using a “learn-by-doing” approach " . Question 31 is -

Customers with no orders for EmployeeID 4

One employee (Margaret Peacock, EmployeeID 4) has placed the most orders. However, there are some customers who've never placed an order with her. Show only those customers who have never placed an order with her.

The solution I did creates a temporary table "cte" and joints it with an existing table. Not pretty or readable actually -

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

I found the following solution online -

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;

Which is nicer.

My question - when can I use OR , AND clauses in a JOIN ? What are the advantages? Is it the fact that a JOIN is executed before the where clause?

Thanks,

Asaf

A JOIN condition can contain any boolean comparison, even subqueries using EXISTS and correlated subqueries. There is no limitation on what can be expressed.

Just a note, however. = and AND are good for performance. Inequalities tend to be performance killers.

As for your particular problem, I think the following is a more direct interpretation of the question:

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

That is, get all customers for whom no order exists with employee 4.

Generally I'd recommend that you always choose the most readable version of the query unless you can actually measure a performance difference with realistic data. The cost based optimiser should pick a good way of executing the query to return the results you want in this case.

For me the JOIN is a lot more readable than the CTE.

Here's is another Solution

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM