I’ll be using the AdventureWorks Database to illustrate my problem.
I need to show for a particular customer a list of OrderDate with the most Orders.
My intial attempt was as follows:
SELECT CustomerID, OrderDate, COUNT(1) Cnt FROM Sales.SalesOrderHeader WHERE CustomerID = 11300 GROUP BY CustomerID, OrderDate ORDER BY Cnt DESC
This will get us the following result:
CustomerID OrderDate Cnt ----------- ---------- ---- 11300 2003-11-22 00:00:00.000 2 11300 2004-01-28 00:00:00.000 2 11300 2004-02-18 00:00:00.000 2 11300 2004-02-08 00:00:00.000 2 11300 2004-02-15 00:00:00.000 1 11300 2004-03-11 00:00:00.000 1 11300 2004-03-24 00:00:00.000 1 11300 2004-03-30 00:00:00.000 1 11300 2004-04-28 00:00:00.000 1 11300 2004-05-03 00:00:00.000 1 11300 2004-05-17 00:00:00.000 1 11300 2004-06-18 00:00:00.000 1 ...
Not exactly what I wanted, as the result should only show all records where Cnt = 2, like so:
CustomerID OrderDate Cnt ----------- ---------- ---- 11300 2003-11-22 00:00:00.000 2 11300 2004-01-28 00:00:00.000 2 11300 2004-02-18 00:00:00.000 2 11300 2004-02-08 00:00:00.000 2
I’m stuck because I can’t wrap my mind around two problems:
1) A customer might have more than one OrderDate with the same Cnt value. This means I can’t do something like TOP 1 to get the desired result.
2) Because the number of Orders for each customer may be different, I cannot use the following SQL statement:
SELECT CustomerID, OrderDate, COUNT(1) Cnt FROM Sales.SalesOrderHeader WHERE CustomerID = 11300 GROUP BY CustomerID, OrderDate HAVING COUNT(1) > 1 ORDER BY Cnt DESC
This will work for getting the right result for this customer, but will definitely be wrong if the next customer has only one Order for a particular day.
So, either the query is impossible in this situation, or I am approaching the query in the wrong way. Any ideas on this problem is appreciated.
Also, since this will be a query in a stored procedure, any ideas on solving this in T-SQL will be acceptable.
UPDATE: Thanks to Mehrdad, I’ve been introduced to Common Table Expressions, and Life is Good®. 🙂
You should use
TOPnWITH TIESclause to accomplish the task:Alternatively, you can use a common table expression (CTE) to solve the problem. This solution requires SQL Server 2005 or higher:
If you’re using the CTE method, make sure the previous statement is terminated by a semicolon (if it’s not the first statement). It’s required before a CTE expression.