Sous-requête SQL / join

Eh bien, je suis un débutant en SQL alors excusez SVP si ce problème est trop novice pour vous. Dans Northwind (je suis sûr que tout le monde est au courant de Northwind) – j'essaie d'get pour chaque mois le produit le plus vendu (en quantité) et celui qui s'est le less vendu en 1997 (commands, détails de command, arrays de produits) )

Merci

MISE À JOUR : C'est ce que j'ai jusqu'ici

Select p.productname, Datepart(MM,o.OrderDate), od.Quantity from orders o inner join [Order Details] od on o.OrderID = od.OrderID inner join Products p on p.ProductID=od.ProductID Where YEAR(o.OrderDate)=1997 Group by Datepart(MM,o.OrderDate), od.Quantity,p.productname 

J'ai trouvé une solution qui résout votre problème. C'est une déclaration sélective avec 3 sous-sélections mais cela fonctionne et a le produit le plus et le less vendu sur la même ligne:

 select a.month, (select top 1 p.ProductName as pid from Northwind.dbo.[Order Details] od1 left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID left join Northwind.dbo.Products p on p.ProductID = od1.ProductID where YEAR(o.OrderDate)=1997 and DATEPART(MM,o.OrderDate) = a.month group by p.ProductName, DATEPART(MM,o.OrderDate) having sum(od1.Quantity) = MAX(a.qty)), max(a.qty) as maxQty, (select top 1 p.ProductName as pid from Northwind.dbo.[Order Details] od1 left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID left join Northwind.dbo.Products p on p.ProductID = od1.ProductID where YEAR(o.OrderDate)=1997 and DATEPART(MM,o.OrderDate) = a.month group by p.ProductName, DATEPART(MM,o.OrderDate) having sum(od1.Quantity) = MIN(a.qty)), min(a.qty) as minQty from (select p.ProductName as pid, DATEPART(MM,o.OrderDate) as month, sum(od1.Quantity) as qty from Northwind.dbo.[Order Details] od1 left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID left join Northwind.dbo.Products p on p.ProductID = od1.ProductID where YEAR(o.OrderDate)=1997 group by p.ProductName, DATEPART(MM,o.OrderDate)) as a group by a.month 

Je suis sûr que quelque chose de plus intelligent aurait pu être fait en utilisant des tables temporaires

Ce n'est pas un problème novice. C'est une commune, mais c'est aussi une sueur assez difficile à get. Et ils ont souvent recours à plusieurs instructions SQL.

Mais vous, mon ami, avez de la chance! Vous êtes sur le sharepoint venir avec moi dans le monde des fonctions analytiques. Mais rassurez-vous, il y a d'autres façons d'y remédier au cas où cela ne vous plairait pas.

Je suppose que vous êtes juste en train de bricoler avec SQL, et que vous voulez juste en savoir plus. Si vous essayez réellement de résoudre un problème spécifique, il serait utile que vous soyez plus précis sur ces deux points:

  1. À quoi voulez-vous que votre set de résultats ressemble? Vous attendez 12 lignes, avec les colonnes "Mois", "Top Vendeur", "Bottom Seller"? Est-ce que 24 lignes dans un set de résultats sont correctes? Est-ce que deux sets de résultats sont corrects?
  2. Est-ce que "vendu le less" inclut des produits qui ne vendent rien? (Par exemple, ils n'apparaissent pas dans le tableau Détails de la command pour le mois.)

Le SQL:

 WITH ProductSalesPerMonth AS ( SELECT DATEPART(MM, O.OrderDate) AS MonthNum, OD.ProductID, SUM(OD.Quantity) AS Quantity FROM Orders O JOIN [Order Details] OD ON O.OrderID = OD.OrderID WHERE O.OrderDate BETWEEN '19970101' AND '19971231' GROUP BY DATEPART(MM, O.OrderDate), OD.ProductID ), RankedProductSalesPerMonth AS ( SELECT PSPM.*, ROW_NUMBER() OVER (PARTITION BY PSPM.MonthNum ORDER BY PSPM.Quantity ASC) AS Rank_SoldLeast, ROW_NUMBER() OVER (PARTITION BY PSPM.MonthNum ORDER BY PSPM.Quantity DESC) AS Rank_SoldMost FROM ProductSalesPerMonth PSPM ) SELECT PS.MonthNum, P.ProductName, PS.Quantity, CASE WHEN Rank_SoldMost = 1 THEN 'Top Seller' WHEN Rank_SoldLeast = 1 THEN 'Bottom Seller' ELSE 'Only Seller' END AS SalesRank FROM RankedProductSalesPerMonth PS JOIN Products P ON P.ProductID = PS.ProductID WHERE (Rank_SoldMost = 1 OR Rank_SoldLeast = 1) ORDER BY MonthNum ASC, Quantity DESC ; 

Le résultat:

 MonthNum ProductName Quantity SalesRank 1 Geitost 119 Top Seller 1 Konbu 2 Bottom Seller 2 Pâté chinois 180 Top Seller 2 Gorgonzola Telino 3 Bottom Seller 3 Raclette Courdavault 162 Top Seller 3 Konbu 1 Bottom Seller 

Peut-être que vous voyez cela et dites "Jeezuz!", Alors voici une explication rapide du code.

WITH vous permet de créer une sorte de sous-requête appelée "Common Table Expression". Dans SQL Server, il est supposé fonctionner comme une vue. Les CTE peuvent se referencer les uns les autres. Je les utilise parce que je pense qu'il est plus facile de comprendre les composants individuels qu'un grand SELECT où vous vous référez à DATEPART(MM, O.OrderDate) et SUM(OD.Quantity) partout. Cela nous permet également de reporter les tables jointes (comme Product ) jusqu'à ce que nous ayons réellement besoin de ces informations.

Notre première clause fait notre regroupement et sommation par mois, par produit. C'est tout.

La deuxième clause identifie les vendeurs supérieurs et inférieurs. Dans SQL Server, un moyen courant de find un logging sur un groupe consiste à partitionner et sortinger de sorte que l'logging que vous voulez bulles au sumt d'une list classée. En sortingant par quantité DESC, notre meilleur vendeur obtiendra un "1" dans la colonne classé_SoldMost. Similaire pour le vendeur en bas.

La troisième clause nous permet de filterr vers nos vendeurs haut / bas, puis décorer le ProductID avec les informations sur le produit.

Et c'est tout. Si ce n'est pas ce que vous demandiez ou si vous avez des questions, éloignez-vous.

Il est difficile de dire ce que vous requestz, surtout lorsque vous ne fournissez aucun schéma pour vos tables. Pour commencer à apprendre les instructions JOIN dans SQL, cependant, je suggère le guide visuel de Jeff Atwood