Справка по операторам SQL - выберите список CustomerID, OrderDate с наибольшим количеством записей в таблице - PullRequest
2 голосов
/ 07 декабря 2008

Я буду использовать 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) Клиент может иметь более одной OrderDate с одинаковым значением Cnt. Это означает, что я не могу сделать что-то вроде 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 меня познакомили с Общими выражениями таблиц и Life is Good®. :)

Ответы [ 2 ]

3 голосов
/ 07 декабря 2008

Для выполнения задачи вы должны использовать предложение 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 голос
/ 07 декабря 2008

У меня нет удобной для тестирования копии AdventureWorks, но может ли помочь предложение WITH TIES? Вы можете сделать что-то вроде:

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

... который должен получить все строки, соответствующие значению в предложении ORDER BY (количество).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...