简体   繁体   中英

SQL Count in MS Access

I have a problem with the COUNT function in SQL. I want to count the number of orders placed by a customer in 2013. The problem I am having is that I cannot display "0" if a customer did not place any orders in 2013.

The query I used is as follows:

SELECT Customer.CustomerID, Count(Orders.OrderID) AS OrderCount
FROM Customer LEFT JOIN Orders ON Customer.[CustomerID] = Orders.[CustomerID]
WHERE YEAR(Orders.OrderDate)=2013
GROUP BY Customer.CustomerID
ORDER BY Count(Orders.OrderID) DESC , Customer.CompanyName;

To illustrate, suppose I have a table like this:

  OrderID    OrderYear  CustomerID
    12          2013         1
    15          2013         2
    18          2013         1
    22          2012         3

What I want my query to return is something like this:

  CustomerID OrderCount
      1           2
      2           1  
      3           0

But instead what I get is as follows:

   CustomerID OrderCount
      1           2
      2           1 

Thank you in advance.

You are almost there...
The reason you are not getting the customers that didn't make any orders is that you have a condition on the OrderDate .

While the left join means that you should return customers even if they have no orders, the condition on the OrderDate means that only customers with orders in 2013 will be returned.

To solve this, all you have to do is add to this condition another option - the OrderDate is null. this can be achieved by simply adding OR Orders.OrderDate IS NULL to your where clause:

SELECT Customer.CustomerID, Count(Orders.OrderID) AS OrderCount
FROM Customer LEFT JOIN Orders ON Customer.[CustomerID] = Orders.[CustomerID]
WHERE YEAR(Orders.OrderDate)=2013
OR Orders.OrderDate IS NULL -- Added this row to your query
GROUP BY Customer.CustomerID
ORDER BY Count(Orders.OrderID) DESC , Customer.CompanyName;

Update

It's been a while since my access days, so I'm not sure if all of the next options will work on access.
They all work on sql server ( you can see the fiddle here ).

Option #1: Move the condition of the OrderDate from the where caluse to the on clause:

SELECT Customer.CustomerID, Count(Orders.OrderID) AS OrderCount
FROM Customer LEFT JOIN Orders ON Customer.[CustomerID] = Orders.[CustomerID]
AND YEAR(Orders.OrderDate)=2013
GROUP BY Customer.CustomerID, Customer.CompanyName
ORDER BY OrderCount DESC, CompanyName;

Option #2: Use a derived table to get only the orders from 2013

SELECT Customer.CustomerID, Count(OrderID) AS OrderCount
FROM Customer LEFT JOIN 
(
   SELECT OrderID, CustomerID
   FROM Orders 
   WHERE YEAR(OrderDate)=2013
) OrdersIn2013
ON Customer.[CustomerID] = OrdersIn2013.[CustomerID]
GROUP BY Customer.CustomerID, Customer.CompanyName
ORDER BY OrderCount DESC, CompanyName;

Option #3 : Use a subquery to return the orders count

SELECT Customer.CustomerID, 
       (SELECT COUNT(OrderId)
        FROM Orders
        WHERE Orders.CustomerId = Customer.CustomerId
        AND YEAR(OrderDate)=2013
        ) As OrderCount
FROM Customer
ORDER BY OrderCount DESC, CompanyName;

Option #2 is my personal favorit, but option #1 has probably the same performance with less code, so some will argue it's the best.
Option #3 is the worst, since it is using a subQuery.

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