2015-05-17 2 views
0

У меня проблема с функцией COUNT в SQL. Я хочу рассчитать количество заказов, размещенных клиентом в 2013 году. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу отобразить «0», если клиент не сделал никаких заказов в 2013 году.SQL Count в MS Access

Запрос, который я использовал, следующий :

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; 

для иллюстрации предположим, что у меня есть таблица вроде этого:

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

То, что я хочу, чтобы мой запрос, чтобы вернуть что-то вроде этого:

CustomerID OrderCount 
     1   2 
     2   1 
     3   0 

Но вместо того, что я получаю следующим образом:

CustomerID OrderCount 
     1   2 
     2   1 

Спасибо заранее.

+0

Покажите запрос, который вы использовали, также хорошо отформатируйте вывод, чтобы избежать путаницы. – Sachu

ответ

2

Вы почти там ...
Причина, по которой вы не получаете клиентов, которые не делали никаких заказов, состоит в том, что у вас есть условие на OrderDate.

В то время как left join означает, что вы должны возвращать клиентов, даже если у них нет заказов, условие на OrderDate означает, что будут возвращены только клиенты с заказами в 2013 году.

Чтобы решить эту проблему, все, что вам нужно сделать, это добавить к этому условию другую опцию - OrderDate - null. это может быть достигнуто путем простого добавления OR Orders.OrderDate IS NULL к вашему где п:

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

Это было время, так как мои дни доступа, так что я не уверен, что все последующие опции будут работать на доступ.
Все они работают на сервере sql (you can see the fiddle here).

Вариант № 1: Move состояние OrderDate от где caluse к о п:

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; 

Вариант № 2: Используйте производную таблицу, чтобы получить только заказы от 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; 

Вариант № 3: Используйте подзапрос для возврата рассчитывать заказы

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; 

Вариант № 2 мой личный Favorit, но вариант # 1, вероятно, имеет такую ​​же производительность, с меньшим количеством кода, поэтому некоторые будут утверждать, что это самое лучшее.
Вариант № 3 является наихудшим, так как он использует subQuery.

+0

Большое спасибо! – theakt

+0

Что делать, если клиент 3 разместил заказ в 2012 году, но не в 2013 году?Когда я использую «Orders.OrderDate IS NULL», он не возвращает клиента 3, так как он разместил заказ в 2012 году. Я обновил вопрос, чтобы он отражал текущую ситуацию. – theakt

+0

Вы можете использовать подзапрос или производную таблицу для этой ситуации. Не могу сейчас привести пример, но я сделаю это позже сегодня вечером. –