Совет SQL-запроса - получить предыдущий заказ клиента

У меня есть следующая таблица

custid ordid количество даты
1 A2 12 2008-01-05
2 A5 5 2008-01-02
1 A1 5 2008-01-01
2 A7 3 2007-02-05

Какой лучший способ получить предыдущий заказ для каждого клиента?

Спасибо

12.12.2008 07:35:31
4 ОТВЕТА
РЕШЕНИЕ

Если под «предыдущим» вы подразумеваете «предыдущий»:

SELECT TOP 1
  ordid
FROM
  orders
WHERE
  custid = @custid
  and datesold < (SELECT MAX(datesold) FROM orders i where i.custid = orders.custid)
ORDER BY
  datesold DESC

Конечно, datesoldэто должен быть DATETIME с достаточно четкими значениями, чтобы это работало. Одного свидания будет недостаточно. Например, если у вас есть дата создания записи, это будет хорошей заменой datesold.

3
12.12.2008 07:48:34

Распространенным решением для такого рода проблем является выбор Max (dateold) и получение последней версии таким образом. Это нормально, если комбинация custid / dateold уникальна, но если в один день было два заказа, это может привести к дублированию.

Если у вас SQL 2005 или выше, вы можете использовать функцию Row_Number, чтобы ранжировать заказы каждого клиента и выбрать первый для каждого:

SELECT custid, ordid, qty, datesold
FROM (
    SELECT *, 
        Row_Number() OVER (PARTITION BY custid ORDER BY datesold desc) as 'Rank'
    FROM tbl
)
WHERE Rank = 1

Чтобы убедиться, что он всегда выбирает один и тот же элемент, даже если они имеют одинаковую дату, добавьте еще несколько элементов (например, RowID, recieptNumber) в предложение ORDER BY Row_number.

Если у вас нет SQL 2005, добавление идентификатора столбца может сделать аналогичные вещи:

SELECT custid, ordid, qty, datesold
FROM tbl
WHERE id = 
    (SELECT TOP 1 id FROM tbl a WHERE custid = a.custID ORDER BY dateSold)

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

Если вам повезло, что вы хотите обработать последний заказ, вы можете:

SELECT custid, ordid, qty, datesold
FROM tbl
INNER JOIN (
    SELECT a.id FROM tbl a GROUP BY tbl.custId
) s ON tbl.id = s.id
1
12.12.2008 07:54:38
Как бы "ROWNUMBER OVER (... ORDER BY DateSold DESC)" было бы более правильным или конкретным, чем "TOP 1 MAX (DateSold)", учитывая тот факт, что в поле сохраняется только часть даты? Я думаю, что он будет вести себя так же: дать вам одну из подходящих строк (первая в порядке таблицы).
Tomalak 12.12.2008 08:17:06

Предположение: Дата продажи будет в порядке возрастания (дата предыдущего заказа будет меньше текущей)

Допустим, вы хотите получить заказ до A5 для клиента 2. Вот как может быть выполнен запрос.


SELECT TOP 1 *
FROM Orders
WHERE DateSold < (SELECT DateSold FROM Orders WHERE CustId = 2 and OrdID = A5)
AND CustId = 2 

0
12.12.2008 07:50:08
Вам понадобится предложение ORDER BY, чтобы сделать эту работу правильно
Tom H 12.12.2008 12:44:24
Том: где, по вашему мнению, требуется Order By?
shahkalpesh 12.12.2008 17:47:53
В конце запроса. В противном случае вы получите первый ряд с более ранней датой, чем A5. Это может быть не последняя дата, хотя. В его примере данных есть только один другой порядок, но это только данные образца.
Tom H 12.12.2008 18:00:33

Это очень похоже на другой вопрос, который вы задали.

SELECT
     T1.ordid
FROM
     dbo.Sales T1
INNER JOIN dbo.Sales T2 ON
     T2.custid = T1.custid AND
     T2.datesold > T1.datesold
LEFT OUTER JOIN dbo.Sales T3 ON
     T3.custid = T1.custid AND
     T3.datesold > T1.datesold AND
     T3.datesold < T2.datesold
WHERE
     T1.custid = @custid AND
     T3.custid IS NULL

То же самое касается строк с одинаковыми значениями даты продажи.

0
12.12.2008 12:48:57