SQL Server: SELECT только строки с MAX (DATE)

У меня есть таблица данных (db - MSSQL):

    ID  OrderNO PartCode  Quantity DateEntered
    417 2144     44917    100      18-08-11
    418 7235     11762    5        18-08-11
    419 9999     60657    100      18-08-11
    420 9999     60657    90       19-08-11

Я хотел бы сделать запрос, который возвращает OrderNO, PartCode и Quantity, но только для последнего зарегистрированного заказа.

В таблице примеров я хотел бы получить следующую информацию:

     OrderNO PartCode  Quantity     
     2144     44917    100      
     7235     11762    5        
     9999     60657    90      

Обратите внимание, что для заказа 9999 была возвращена только одна строка.

Спасибо!

Ответ 1

Если rownumber() over(...) доступен для вас....

select OrderNO,
       PartCode,
       Quantity
from (select OrderNO,
             PartCode,
             Quantity,
             row_number() over(partition by OrderNO order by DateEntered desc) as rn
      from YourTable) as T
where rn = 1      

Ответ 2

Лучший способ - Микаэль Эрикссон, если ROW_NUMBER() доступен вам.

Следующее лучше всего - присоединиться к запросу, как ответ Cularis.

В качестве альтернативы самым простым и прямым способом является коррелированный суб-запрос в предложении WHERE.

SELECT
  *
FROM
  yourTable AS [data]
WHERE
  DateEntered = (SELECT MAX(DateEntered) FROM yourTable WHERE orderNo = [data].orderNo)

Или...

WHERE
  ID = (SELECT TOP 1 ID FROM yourTable WHERE orderNo = [data].orderNo ORDER BY DateEntered DESC)

Ответ 3

select OrderNo,PartCode,Quantity
from dbo.Test t1
WHERE EXISTS(SELECT 1
         FROM dbo.Test t2
         WHERE t2.OrderNo = t1.OrderNo
           AND t2.PartCode = t1.PartCode
         GROUP BY t2.OrderNo,
                  t2.PartCode
         HAVING t1.DateEntered = MAX(t2.DateEntered))

Это самый быстрый из всех запросов, указанных выше. Стоимость запроса составила 0,0070668.

Предпочтительный ответ выше, Mikael Eriksson, имеет стоимость запроса 0,0146625

Вы можете не заботиться о производительности для такого небольшого образца, но в больших запросах все это добавляется.

Ответ 4

SELECT t1.OrderNo, t1.PartCode, t1.Quantity
FROM table AS t1
INNER JOIN (SELECT OrderNo, MAX(DateEntered) AS MaxDate
            FROM table
            GROUP BY OrderNo) AS t2
ON (t1.OrderNo = t2.OrderNo AND t1.DateEntered = t2.MaxDate)

Внутренний запрос выбирает все OrderNo с максимальной датой. Чтобы получить другие столбцы таблицы, вы можете присоединиться к ним на OrderNo и MaxDate.

Ответ 5

Для MySql вы можете сделать что-то вроде следующего:

select OrderNO, PartCode, Quantity from table a
join (select ID, MAX(DateEntered) from table group by OrderNO) b on a.ID = b.ID

Ответ 6

И вы также можете использовать этот оператор select как левый запрос соединения... Пример:

... left join (select OrderNO,
   PartCode,
   Quantity from (select OrderNO,
         PartCode,
         Quantity,
         row_number() over(partition by OrderNO order by DateEntered desc) as rn
  from YourTable) as T where rn = 1 ) RESULT on ....

Надеюсь, что это поможет кому-то, кто ищет это:)

Ответ 7

Попробуйте избежать использования IN JOIN

SELECT SQL_CALC_FOUND_ROWS *  FROM (SELECT  msisdn, callid, Change_color, play_file_name, date_played FROM insert_log
   WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
 ORDER BY callid ASC) t1 JOIN (SELECT MAX(date_played) AS date_played FROM insert_log GROUP BY callid) t2 ON t1.date_played=t2.date_played

Ответ 8

rownumber() over (...) работает, но мне не понравилось это решение по двум причинам.  - Эта функция недоступна, если вы используете более старую версию SQL, такую ​​как SQL2000  - Зависимость от функции и на самом деле не читается.

Другое решение:

SELECT tmpall.[OrderNO] ,
       tmpall.[PartCode] ,
       tmpall.[Quantity] ,
FROM   (SELECT [OrderNO],
               [PartCode],
               [Quantity],
               [DateEntered]
        FROM   you_table) AS tmpall
       INNER JOIN (SELECT [OrderNO],
                          Max([DateEntered]) AS _max_date
                   FROM   your_table
                   GROUP  BY OrderNO ) AS tmplast
               ON tmpall.[OrderNO] = tmplast.[OrderNO]
                  AND tmpall.[DateEntered] = tmplast._max_date