SQL语句帮助 - 选择表中包含最多记录的CustomerID,OrderDate列表

时间:2008-12-07 10:27:13

标签: sql sql-server-2005

我将使用AdventureWorks Database来说明我的问题。

我需要为特定客户显示包含最多订单的OrderDate列表。

我的尝试如下:

SELECT CustomerID, OrderDate, COUNT(1) Cnt
FROM Sales.SalesOrderHeader
WHERE CustomerID = 11300
GROUP BY CustomerID, OrderDate
ORDER BY Cnt DESC

这将得到以下结果:

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
...

不完全是我想要的,因为结果应该只显示Cnt = 2的所有记录,如下所示:

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

我被困了,因为我无法解决两个问题:

1)客户可能有多个具有相同Cnt值的OrderDate。这意味着我不能做像TOP 1这样的事情来获得理想的结果 2)因为每个客户的订单数量可能不同,所以我不能使用以下SQL语句:

SELECT CustomerID, OrderDate, COUNT(1) Cnt
FROM Sales.SalesOrderHeader
WHERE CustomerID = 11300
GROUP BY CustomerID, OrderDate HAVING COUNT(1) > 1
ORDER BY Cnt DESC

这将有助于为该客户获得正确的结果,但如果下一个客户在特定日期只有一个订单,那肯定会出错。

因此,在这种情况下查询是不可能的,或者我以错误的方式接近查询。关于这个问题的任何想法表示赞赏。

此外,由于这将是存储过程中的查询,因此在T-SQL中解决此问题的任何想法都是可以接受的。

更新:感谢Mehrdad,我被介绍到Common Table Expressions,而LifeisGood®。 :)

2 个答案:

答案 0 :(得分:3)

您应该使用TOP n WITH TIES子句来完成任务:

SELECT TOP 1 WITH TIES CustomerID, OrderDate, COUNT(*) Cnt
FROM Sales.SalesOrderHeader
WHERE CustomerID = 11300
GROUP BY CustomerID, OrderDate
ORDER BY Cnt DESC

或者,您可以使用公用表表达式(CTE)来解决问题。此解决方案需要SQL Server 2005或更高版本:

WITH MyTable AS (SELECT CustomerID, OrderDate, COUNT(*) Cnt
                 FROM Sales.SalesOrderHeader
                 WHERE CustomerID = 11300
                 GROUP BY CustomerID, OrderDate)
SELECT CustomerID, OrderDate, Cnt
FROM MyTable
WHERE Cnt = (SELECT MAX(Cnt) FROM MyTable);

如果您正在使用CTE方法,请确保先前的语句以分号结束(如果它不是第一个语句)。在CTE表达之前需要它。

答案 1 :(得分:1)

我没有使用的AdventureWorks副本,但是WITH TIES子句可以帮忙吗?你可以这样做:

SELECT TOP 1 WITH TIES CustomerID, OrderDate, COUNT(*) Cnt
...
ORDER BY COUNT(*) DESC

...它应该为您提供与ORDER BY子句中的值匹配的所有行(计数)。