SQL Server: ВЫБЕРИТЕ только строки с МАКС. (ДАТА) - PullRequest
92 голосов
/ 19 августа 2011

У меня есть таблица данных (база данных 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 была возвращена только одна строка.

Ответы [ 9 ]

156 голосов
/ 19 августа 2011

Если вам доступно 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      
53 голосов
/ 19 августа 2011

Лучший способ - это Микаэль Эрикссон, если вам доступно 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)
26 голосов
/ 04 ноября 2014
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.

Предпочтительный ответ Микаэля Эрикссона, приведенный выше, имеет стоимость запроса 0,0146625

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

10 голосов
/ 19 августа 2011
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.

2 голосов
/ 04 января 2018

Если у вас есть индексированные ID и OrderNo, вы можете использовать IN: (Я ненавижу простоту торговли из-за неясности, просто чтобы сохранить несколько циклов):

select * from myTab where ID in(select max(ID) from myTab group by OrderNo);
1 голос
/ 29 июля 2017

rownumber () over (...) работает, но мне не понравилось это решение по 2 причинам. - Эта функция недоступна при использовании более старой версии 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
1 голос
/ 07 октября 2014

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

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

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

1 голос
/ 19 августа 2011

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

select OrderNO, PartCode, Quantity from table a
join (select ID, MAX(DateEntered) from table group by OrderNO) b on a.ID = b.ID
0 голосов
/ 14 мая 2017

Старайтесь избегать при использовании 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...