Загадка SQL, как выбрать последнюю дату для части, но только 1 строка на часть (уникальная) - PullRequest
5 голосов
/ 09 сентября 2010

Я пытаюсь обернуть голову этим утром

Я пытаюсь показать inventory статус для деталей (для наших продуктов), и этот запрос становится сложным, только если я пытаюсь вернуть все детали.

Позвольте мне выложить это:

  • один стол inventoryReport
  • У меня есть отдельный список X частей, которые я хочу отобразить, в результате должно быть X # рядов (1 строка на деталь, показывающую последнюю запись инвентаря).
  • состоит из датированных записей об изменениях запасов (поэтому мне нужна только запись даты LATEST для каждой детали).
  • все данные, содержащиеся в этой единственной таблице, поэтому объединений не требуется.

В настоящее время для 1 отдельной части это довольно просто, и я могу сделать это, выполнив следующий sql (чтобы дать вам некоторое представление):

SELECT     TOP (1) ldDate, ptProdLine, inPart, inSite, inAbc, ptUm, inQtyOh + inQtyNonet AS in_qty_oh, inQtyAvail, inQtyNonet, ldCustConsignQty, inSuppConsignQty
FROM         inventoryReport
WHERE     (ldPart = 'ABC123')
ORDER BY ldDate DESC

, что дает мне мой ТОП-1 ряд, такой простой для каждой части, однако мне нужно показать все X (скажем, 30 частей). Так что мне нужно 30 строк, с таким результатом. Конечно, простым решением было бы зациклить X # вызовов sql в моем коде (но это было бы дорого), и этого было бы достаточно, но для этой цели я хотел бы еще немного поработать с этим SQL, чтобы уменьшить количество вызовов x # до db. (если не нужно) до 1 запроса.

Из того, что я вижу здесь, мне нужно как-то отслеживать последнюю дату для каждого элемента при поиске набора результатов.

Я бы в конечном итоге сделал

WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc)

для ограничения частей, которые мне нужны. Надеюсь, я достаточно ясно изложил свой вопрос. Дайте мне знать, если у вас есть идея. Я не могу сделать DISTINCT, так как строки не совпадают, дата должна быть самой последней, и мне нужно максимум X строк.

Мысли? Я застрял ...

Ответы [ 3 ]

5 голосов
/ 09 сентября 2010
  SELECT *
  FROM   (SELECT i.*,
      ROW_NUMBER() OVER(PARTITION BY ldPart ORDER BY ldDate DESC) r
      FROM   inventoryReport i
      WHERE  ldPart in ('ABC123', 'BFD21', 'AA123', etc)
         )
  WHERE  r = 1
2 голосов
/ 09 сентября 2010

РЕДАКТИРОВАТЬ : обязательно проверьте производительность каждого решения. Как указано в этом вопросе , метод CTE может выиграть, если использовать ROW_NUMBER.

;with cteMaxDate as (
    select ldPart, max(ldDate) as MaxDate
        from inventoryReport
        group by ldPart
)
SELECT md.MaxDate, ir.ptProdLine, ir.inPart, ir.inSite, ir.inAbc, ir.ptUm, ir.inQtyOh + ir.inQtyNonet AS in_qty_oh, ir.inQtyAvail, ir.inQtyNonet, ir.ldCustConsignQty, ir.inSuppConsignQty
    FROM cteMaxDate md
        INNER JOIN inventoryReport ir
            on md.ldPart = ir.ldPart
                and md.MaxDate = ir.ldDate
2 голосов
/ 09 сентября 2010

Вам необходимо присоединиться к подзапросу:

SELECT i.ldPart, x.LastDate, i.inAbc
FROM inventoryReport i
INNER JOIN (Select ldPart, Max(ldDate) As LastDate FROM inventoryReport GROUP BY ldPart) x
on i.ldPart = x.ldPart and i.ldDate = x.LastDate
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...