Northwindデータベースを使用して、多少複雑なクエリを作成することにより、SQLスキルを更新しています。残念ながら、最後のユースケースの解決策は見つかりませんでした。「1997年のすべてのカテゴリについて、上位5つの注文の合計を取得してください。」
関連するテーブルは次のとおりです。
Orders(OrderId, OrderDate)
Order Details(OrderId, ProductId, Quantity, UnitPrice)
Products(ProductId, CategoryId)
Categories(CategoryId, CategoryName)
私は次のクエリを試しました
SELECT c.CategoryName, SUM(
(SELECT TOP 5 od2.UnitPrice*od2.Quantity
FROM [Order Details] od2, Products p2
WHERE od2.ProductID = p2.ProductID
AND c.CategoryID = p2.CategoryID
ORDER BY 1 DESC))
FROM [Order Details] od, Products p, Categories c, Orders o
WHERE od.ProductID = p. ProductID
AND p.CategoryID = c.CategoryID
AND od.OrderID = o.OrderID
AND YEAR(o.OrderDate) = 1997
GROUP BY c.CategoryName
さて...集計関数ではサブクエリは許可されていません。この問題に関する他の記事を読みましたが、特定のユースケースの解決策が見つかりませんでした。あなたが私を助けてくれることを願っています...
通常、集計関数ではサブクエリは許可されていません。代わりに、集計を移動しますinsideサブクエリ。この場合、top 5
のため、追加のレベルのサブクエリが必要になります。
SELECT c.CategoryName,
(select sum(val)
from (SELECT TOP 5 od2.UnitPrice*od2.Quantity as val
FROM [Order Details] od2, Products p2
WHERE od2.ProductID = p2.ProductID
AND c.CategoryID = p2.CategoryID
ORDER BY 1 DESC
) t
)
FROM [Order Details] od, Products p, Categories c, Orders o
WHERE od.ProductID = p. ProductID
AND p.CategoryID = c.CategoryID
AND od.OrderID = o.OrderID
AND YEAR(o.OrderDate) = 1997
GROUP BY c.CategoryName, c.CategoryId
過剰なサブクエリの代わりに [〜#〜] cte [〜#〜] with ROW_NUMBER ランキング関数を使用します。
;WITH cte AS
(
SELECT c.CategoryName, od2.UnitPrice, od2.Quantity,
ROW_NUMBER() OVER(PARTITION BY c.CategoryName ORDER BY od2.UnitPrice * od2.Quantity DESC) AS rn
FROM [Order Details] od JOIN Products p ON od.ProductID = p.ProductID
JOIN Categories c ON p.CategoryID = c.CategoryID
JOIN Orders o ON od.OrderID = o.OrderID
WHERE o.OrderDate >= DATEADD(YEAR, DATEDIFF(YEAR, 0, '19970101'), 0)
AND o.OrderDate < DATEADD(YEAR, DATEDIFF(YEAR, 0, '19970101')+1, 0)
)
SELECT CategoryName, SUM(UnitPrice * Quantity) AS val
FROM cte
WHERE rn < 6
GROUP BY CategoryName
ここの間違いなくサブクエリの問題は、これに関する 優秀な記事 です(元々Access向けに書かれていますが、構文は同じです)、orderdate = 1997は1997年1月1日の注文日を与えます-datepartが必要です(年、注文日)= 1997、各カテゴリに対して(最大5)行が返されたら、返された行をカプセル化して集計
レコードが日付で並べ替えられているAccessサブクエリで、非常によく似た問題が発生しました。 「最後の」集計関数を使用すると、すべてのサブクエリを通過し、Accessテーブルからデータの最後の行を取得しましたが、意図したとおりの並べ替えられたクエリは取得しませんでした。最初のかっこ内で集計関数を使用するようにクエリを書き直すこともできました(以前に提案されたように) 「必要な値を取得する集約関数。結果を最新に保つために、将来的に更新クエリを実行します。効率的ではありませんが、効果的です。