SQL窗口功能
我目前正在根据销售额的总和降序排序产品,并根据2007年每个产品的销售额总和排名,如果产品在该年的销售额最高,则排名第一,以此类推SQL窗口功能,sql,sql-server,tsql,Sql,Sql Server,Tsql,我目前正在根据销售额的总和降序排序产品,并根据2007年每个产品的销售额总和排名,如果产品在该年的销售额最高,则排名第一,以此类推 目前,除了RankOf2008和DRankOf2008列之外,我的数据库表看起来与图中提到的一样,如果2007年前5名产品中的任何一款在2008年未售出,我想在2008年对2007年的前5名产品进行排名,如上图所示。您可能需要类似的产品 首先获取所有产品的排名,然后按年份进行划分,即按年度对产品进行排名,并借助CTE获取所需数据 SELECT *
目前,除了RankOf2008和DRankOf2008列之外,我的数据库表看起来与图中提到的一样,如果2007年前5名产品中的任何一款在2008年未售出,我想在2008年对2007年的前5名产品进行排名,如上图所示。您可能需要类似的产品 首先获取所有产品的排名,然后按年份进行划分,即按年度对产品进行排名,并借助CTE获取所需数据
SELECT
*
FROM (
SELECT
Product,
SalesAmount,
ROW_NUMBER() OVER (ORDER BY SalesAmount DESC) as RowNum,
RANK() OVER (ORDER BY SalesAmount DESC) as RankOf2007,
DENSE_RANK() OVER (ORDER BY SalesAmount DESC) as DRankOf2007
FROM (
SELECT
c.EnglishProductName as Product,
SUM(a.SalesAmount) as SalesAmount,
b.CalendarYear as CalenderYear
FROM FactInternetSales a
INNER JOIN DimDate b
ON a.OrderDateKey=b.DateKey
INNER JOIN DimProduct c
ON a.ProductKey=c.ProductKey
WHERE b.CalendarYear IN (2007)
GROUP BY c.EnglishProductName,b.CalendarYear
) Sales
) Rankings
WHERE [RankOf2007] <= 5
ORDER BY [SalesAmount] DESC
在最里面的查询中使用条件聚合,即选择年份并有条件地求和其中一个年份:
WITH cte
AS (
SELECT *
FROM (
SELECT Product
,SalesAmount
,CalenderYear
,ROW_NUMBER() OVER (
PARTITION BY CalenderYear ORDER BY SalesAmount DESC
) AS RowNum
,RANK() OVER (
PARTITION BY CalenderYear ORDER BY SalesAmount DESC
) AS RankOf2007
,DENSE_RANK() OVER (
PARTITION BY CalenderYear ORDER BY SalesAmount DESC
) AS DRankOf2007
FROM (
SELECT c.EnglishProductName AS Product
,SUM(a.SalesAmount) AS SalesAmount
,b.CalendarYear AS CalenderYear
FROM FactInternetSales a
INNER JOIN DimDate b ON a.OrderDateKey = b.DateKey
INNER JOIN DimProduct c ON a.ProductKey = c.ProductKey
--WHERE b.CalendarYear IN (2007)
GROUP BY c.EnglishProductName
,b.CalendarYear
) Sales
) Rankings
--WHERE [RankOf2007] <= 5
--ORDER BY [SalesAmount] DESC
)
SELECT a.*
,b.DRankOf2007 AS [DRankOf2008]
,b.RankOf2007 AS [RankOf2008]
FROM cte a
LEFT JOIN cte b ON a.Product = b.Product
AND b.CalenderYear = 2008
WHERE a.CalenderYear = 2007
AND a.[RankOf2007] <= 5
但是SQLServer不符合这里的SQL标准,并且在ORDERBY子句中不具有NULL FIRST/LAST。幸运的是,当按降序排序时,它最后对null进行排序,因此它隐式地执行我们在这里想要的操作
顺便说一下:我们可以在一个步骤中进行聚合和排序,但在这种情况下,我们必须重复求和表达式。这是个人偏好的问题,是用一步较短的查询,还是两步不重复的表达。谢谢您的反馈。这很有用
select
p.productkey,
p.englishproductname as product,
ranked.salesamount2007,
ranked.salesamount2008,
ranked.rankof2007,
ranked.rankof2008
from
(
select
productkey,
salesamount2007,
salesamount2008,
rank() over (order by salesamount2007 desc) as rankof2007,
rank() over (order by salesamount2008 desc) as rankof2008
from
(
select
s.productkey,
sum(case when d.calendaryear = 2007 then s.salesamount end) as salesamount2007,
sum(case when d.calendaryear = 2008 then s.salesamount end) as salesamount2008
from factinternetsales s
inner join dimdate d on d.datekey = s.orderdatekey
where d.calendaryear in (2007, 2008)
group by s.productkey
) aggregated
) ranked
join dimproduct p on p.productkey = ranked.productkey
where ranked.rankof2007 <= 5
order by ranked.rankof2007 desc;
rank() over (order by salesamount2008 desc nulls last) as rankof2008