web-dev-qa-db-fra.com

SQL Server: SELECT uniquement les lignes avec MAX (DATE)

J'ai une table de données (la base de données est 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

Je voudrais faire une requête qui retourne OrderNO, PartCode et Quantity, mais seulement pour la dernière commande enregistrée.

Dans l'exemple de la table, j'aimerais récupérer les informations suivantes:

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

Notez que seule une ligne a été renvoyée pour la commande 9999.

Merci!

86
GEMI

Si rownumber() over(...) est disponible pour vous ....

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      
145
Mikael Eriksson

Le meilleur moyen est Mikael Eriksson, si ROW_NUMBER() est à votre disposition.

La meilleure solution consiste à rejoindre une requête, selon la réponse de Cularis.

La solution la plus simple et la plus simple consiste à utiliser une sous-requête corrélée dans la clause WHERE.

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

Ou...

WHERE
  ID = (SELECT TOP 1 ID FROM yourTable WHERE orderNo = [data].orderNo ORDER BY DateEntered DESC)
48
MatBailie
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))

C'est la plus rapide de toutes les requêtes fournies ci-dessus. Le coût de la requête s'élevait à 0,0070668.

La réponse préférée ci-dessus, de Mikael Eriksson, a un coût de requête de 0,0146625.

Vous ne vous souciez peut-être pas de la performance d’un échantillon aussi petit, mais dans les requêtes volumineuses, tout s’ajoute.

22
tone
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)

La requête interne sélectionne toutes les OrderNo avec leur date maximale. Pour obtenir les autres colonnes de la table, vous pouvez les joindre sur OrderNo et la MaxDate.

9
Jacob

rownumber () over (...) fonctionne mais je n'ai pas aimé cette solution pour 2 raisons . - Cette fonction n'est pas disponible lorsque vous utilisez une version antérieure de SQL telle que SQL2000 - La dépendance à la fonction et n'est pas vraiment lisible.

Une autre solution est:

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
Navid Golforoushan

Et vous pouvez également utiliser cette instruction select en tant que requête de jointure gauche ... Exemple:

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

J'espère que cela aidera quelqu'un qui cherche cela :)

1
idzi

Si vous avez indexé ID et OrderNo, vous pouvez utiliser IN: (je déteste la simplicité de négociation pour des raisons d'obscurité, juste pour économiser quelques cycles):

select * from myTab where ID in(select max(ID) from myTab group by OrderNo);
1
MortenB

Pour MySql, vous pouvez effectuer les opérations suivantes:

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

Essayez d'éviter d'utiliser 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
0