我需要每年退回前 10 种产品,我该如何使用以下查询来做到这一点?
SELECT
DP.ProductID
, DP.Name
, Year(FS.OrderDate) as TheYear
, FS.OrderQty
, FS.OrderAmount
FROM dbo.DimProduct AS DP
LEFT JOIN dbo.FactSales as FS on FS.ProductID = DP.ProductID
我需要每年退回前 10 种产品,我该如何使用以下查询来做到这一点?
SELECT
DP.ProductID
, DP.Name
, Year(FS.OrderDate) as TheYear
, FS.OrderQty
, FS.OrderAmount
FROM dbo.DimProduct AS DP
LEFT JOIN dbo.FactSales as FS on FS.ProductID = DP.ProductID
如果您的 RDBMS 支持,这应该很容易Window Functions
SELECT ProductID,
Name,
TheYear,
OrderQty,
OrderAmount
FROM
(
SELECT DP.ProductID
,DP.Name
,Year(FS.OrderDate) as TheYear
,FS.OrderQty
,FS.OrderAmount,
,ROW_NUMBER() OVER() (PARTITION BY Year(FS.OrderDate)
ORDER BY FS.OrderQty DESC) rn
FROM dbo.DimProduct AS DP
LEFT JOIN dbo.FactSales as FS
on FS.ProductID = DP.ProductID
) s
WHERE rn <= 10
ORDER BY TheYear
当前查询将为您10
提供每个TheYear
基于的产品,FS.OrderQty
因为您没有提到如何整理记录的标准。
(一个 RANKING 函数)将为每个组生成一个数字序列,在这种情况下ROW_NUMBER()
,它是基于 排序的。然后将根据生成的序列的值过滤掉记录。Year(FS.OrderDate)
FS.OrderQty
但是,ifROW_NUMBER()
不会TIE
在具有相同FS.OrderQty
. 如果您希望处理它,请使用DENSE_RANK()
而不是ROW_NUMBER()
.
您想使用该函数row_number()
来获得前 10 名。这假设OrderQty
定义了前 10 名:
select t.*
from (SELECT DP.ProductID, DP.Name, Year(FS.OrderDate) as TheYear, FS.OrderQty, FS.OrderAmount,
row_number() over (partition by Year(FS.OrderDate)
order by fs.OrderAmount desc
) as seqnum
FROM dbo.DimProduct DP LEFT JOIN
dbo.FactSales FS
on FS.ProductID = DP.ProductID
) t
where seqnum <= 10;
该函数row_number()
枚举行,从 1 开始。它在每个组内重新开始,如partition by
子句所定义(在您的情况下为年份)。数字的顺序基于order by
子句(在您的情况下为fs.OrderAmount desc
)。因此,每年的十佳产品将有数字 1-10,where
条款只是选择它们。
SELECT
DP.ProductID
, DP.Name
, Year(FS.OrderDate) as TheYear
, FS.OrderQty
, FS.OrderAmount
, (FS.OrderQty * FS.OrderAmount) AS FS.Total
FROM dbo.DimProduct AS DP
LEFT JOIN dbo.FactSales as FS on FS.ProductID = DP.ProductID
GROUP BY TheYear, DP.ProductID, FS.Total
ORDER BY FS.Total DESC
WHERE seqnum <= 10;