SQL Server max Datetime

Je suis un peu nouveau sur SQL Server et j'essaie d'exécuter une requête très simple qui ressemble à ceci:

SELECT ProductID, o.OrderID, o.CustomerID, CompanyName,OrderDate, Quantity FROM o JOIN [Order Details] od on o.OrderID = od.OrderID JOIN Customers c on c.CustomerID = o.CustomerID WHERE orderdate = (select max(OrderDate) from o where ProductID = od.ProductID) 

Et puis j'ai eu ça.

 ProductID OrderID CustomerID CompanyName OrderDate Quantity 2 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 24 3 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 4 4 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 6 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 7 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 8 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2 10 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 12 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2 13 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 4 14 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 16 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2 20 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 23 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2 32 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1 

mais je veux get le plus récent orderdate pour chaque productID. Comme ça:

entrez la description de l'image ici

Alors que dois-je faire pour l'get?

Cela devrait vous aider à démarrer. Je suppose que les Order Details command ont des éléments de campagne.

 SELECT p.ProductID, o.OrderID, o.CustomerID, o.CompanyName, o.OrderDate FROM dbo.Products p CROSS APPLY ( SELECT TOP 1 * FROM dbo.Orders o WHERE EXISTS ( SELECT * FROM dbo.[Order Details] od WHERE o.OrderID = od.OrderID AND p.ProductID = od.ProductID ) ORDER BY o.OrderDate DESC ) o INNER JOIN dbo.Customers c ON o.CustomerID = c.CustomerID ; 

J'ai supposé que les lignes de [Order Details] pouvaient avoir le même OrderID deux fois, ce qui rend les choses un peu plus compliquées pour get la Quantity (que j'ai OrderID ). Voudriez-vous que cette quantité soit additionnée, ou pour montrer deux rangées? En fonction du résultat que vous voulez et de la façon dont cette table est implémentée, cela pourrait être la solution que vous voulez:

 SELECT p.ProductID, odq.OrderID, odq.CustomerID, odq.CompanyName, odq.OrderDate, odq.Quantity FROM dbo.Products p CROSS APPLY ( SELECT TOP 1 * FROM dbo.Orders o CROSS APPLY ( SELECT TotalQuantity = Sum(Quantity) FROM dbo.[Order Details] od WHERE o.OrderID = od.OrderID AND p.ProductID = od.ProductID ) odq ORDER BY o.OrderDate DESC ) odq INNER JOIN dbo.Customers c ON o.CustomerID = c.CustomerID ; 

Cette requête devrait bien fonctionner tant que vous avez des index appropriés sur vos tables (les Order Details doivent avoir un index ProductID, OrderID et Orders doivent avoir un index commençant par ProductID, OrderDate ). Ses performances devraient restr stables à mesure que datatables du système augmentent.

J'ai dbo.Products que vous avez une table dbo.Products , et en passant de CROSS APPLY à OUTER APPLY (le premier), vous pouvez afficher les produits qui n'ont pas d'ordre. Alternativement, il y a une autre requête possible:

 WITH OrderSequences AS ( SELECT Sequence = Rank() OVER (PARTITION BY od.ProductID ORDER BY o.OrderDate DESC), o.*, od.ProductID, od.Quantity FROM dbo.Orders o INNER JOIN dbo.[Order Details] od ON o.OrderID = od.OrderID ) SELECT o.OrderID, o.CustomerID, o.CompanyName, o.OrderDate, o.ProductID, o.Quantity FROM OrderSequences o INNER JOIN dbo.Customers c ON o.CustomerID = c.CustomerID WHERE Sequence = 1 ; 

Encore une fois, si vous pouvez avoir le même OrderID sur plus d'une ligne dans un ordre (une chose très probable à mon avis), alors vous devrez faire une sorte de sommation, ou tolérer les lignes dupliquées que cela va générer (comme il affichera les deux lignes sur le même ordre si elles étaient, set, la dernière fois que ProductID a été commandé).

Cette deuxième requête risque de ralentir et de ralentir au fur et à mesure que le système vieillit et accumule des données, car il est obligé d'exécuter la fonction de fenêtrage sur chaque ligne de la table (il n'est jamais sûr de find la date la plus haute). ProductID jusqu'à la fin).

 WITH X AS (SELECT ProductID , o.OrderID , o.CustomerID , CompanyName ,OrderDate , Quantity ,ROW_NUMBER() OVER (PARTITION BY od.productid ORDER BY o.OrderDate DESC) rn FROM [Orders] o JOIN [Order Details] od on o.OrderID = od.OrderID join Customers c on c.CustomerID=o.CustomerID ) SELECT ProductID , OrderID , CustomerID , CompanyName , OrderDate , Quantity FROM X WHERE rn = 1 

OU

 SELECT ProductID , OrderID , CustomerID , CompanyName , OrderDate , Quantity FROM (SELECT ProductID , o.OrderID , o.CustomerID , CompanyName ,OrderDate , Quantity ,ROW_NUMBER() OVER (PARTITION BY od.productid ORDER BY o.OrderDate DESC) rn FROM [Orders] o JOIN [Order Details] od on o.OrderID = od.OrderID join Customers c on c.CustomerID=o.CustomerID )x WHERE rn = 1 

En utilisant MAX(OrderDate) dans une sous-requête, il n'y a rien à corréler le max (date) avec le productID dans la requête parente. Ainsi, vous obtiendrez toujours toutes les commands qui ont le Max (Date) du premier ProductID de la jointure Order-Product.

La meilleure façon de faire ce genre de filter est de se joindre à la table o order.

 SELECT ProductID, o.OrderID, o.CustomerID, CompanyName,OrderDate, Quantity FROM o LEFT JOIN o2 ON o.ProductID = o2.ProductID AND o2.OrderDate > o.OrderDate JOIN [Order Details] od on o.OrderID = od.OrderID join Customers c on c.CustomerID=o.CustomerID WHERE o2.OrderDate IS NULL 

Donc, ici, nous joignons toutes les commands d'un produit avec toutes les autres commands du même produit qui ont un plus grand OrderDate, puis filtrons pour celui qui n'a pas de plus grande date de command, de sorte que o.OrderDate sera le MAX(OrderDate) pour chaque ProductID

(Avertissement: Le SQL ci-dessus n'est pas testé et peut nécessiter une modification afin de fonctionner correctement sur votre database, mais l'idée devrait fonctionner pour vos besoins.)