在开发中遇到了一个需求:
有一张进度表ProgressMonthly 字段有 id, projectid, year, month, complete
目标是: 统计所有项目的最新月份的complete 数量
解决思路: 使用分析函数: ......OVER ( PARTITION BY ...... ORDER BY ...... ) 筛选出每个项目的最新月份的数据然后sum()
常用的分析函数有:
就是先把一组数据按照a这个字段进行分割成多个组,然后组内按照b这个字段进行排序
举个例子:
SELECT * ,
ROW_NUMBER() OVER(PARTITION BY Y.Year ORDER BY Y.Month DESC ) RNO
from ProgressMonthly Y
输出如下:
如上图数据会根据year分成2组,每一组会根据month进行排序.
根据我们的需求我们将会在ROW_NUMBER()... , RANK()... 和 DENSE_RANK()... 这三个分析函数选择,它们的区别在哪里呢?
1.ROW_NUMBER()...在遇到month参数相同时也会进行排序
如下图:
2.RANK()... 和 DENSE_RANK()...在遇到month参数相同时 ,相同参数的排序是一样的
如下图:
3. 那RANK()... 和 DENSE_RANK()...的区别在哪呢?
RANK()... 输出如下图(注意红框):
DENSE_RANK()...输出如下图(注意红框):
由图可见:
RANK()...
相同参数保持一致排序后,后面元素还是保持原本排序
DENSE_RANK()...
相同参数保持一致排序后,后面元素还是跟随排序
代码如下:
SELECT *
from (
SELECT *,
DENSE_RANK() OVER(PARTITION BY Y.Year ORDER BY Y.Month DESC ) RNO,
DENSE_RANK() OVER( ORDER BY Y.Year DESC ) RNO2 from ProgressMonthly Y
) X
where x.RNO = 1 AND x.RNO2 = 1
ORDER BY YEAR DESC
输出结果:
最后进行Group up ... SUM()出所有项目的统计值:
代码如下:
SELECT SUM(X.Complete) AS sumComplete
from (
SELECT Y.Year,Y.Complete,
DENSE_RANK() OVER(PARTITION BY Y.Year ORDER BY Y.Month DESC ) RNO,
DENSE_RANK() OVER( ORDER BY Y.[Year] DESC ) RNO2 from ProgressMonthly Y
) X
where X.RNO = 1 AND X.RNO2 = 1
GROUP BY X.Year
ORDER BY YEAR DESC
输出如下:
大功告成!!!