我有一个带有全部记录的SQL表,如下所示:
| Date | Score | + -----------+-------+ | 01/01/2010 | 4 | | 02/01/2010 | 6 | | 03/01/2010 | 10 | ... | 16/03/2010 | 2 |
我将其绘制在图表上,因此我在图表上得到一条漂亮的线,表示随时间推移的得分。迷人的。
现在,我需要做的是在图表上包括平均得分,以便我们可以看到平均得分随时间的变化,因此我可以简单地将其添加到组合中:
SELECT YEAR(SCOREDATE) 'Year', MONTH(SCOREDATE) 'Month', MIN(SCORE) MinScore, AVG(SCORE) AverageScore, MAX(SCORE) MaxScore FROM SCORES GROUP BY YEAR(SCOREDATE), MONTH(SCOREDATE) ORDER BY YEAR(SCOREDATE), MONTH(SCOREDATE)
到目前为止没有问题。
问题是,如何轻松计算每个时间段的百分位数?我不确定这是正确的短语。我总共需要的是:
这是我不明白的第三个。我需要计算5%的百分位数,我可以单独这样做:
SELECT MAX(SubQ.SCORE) FROM (SELECT TOP 45 PERCENT SCORE FROM SCORES WHERE YEAR(SCOREDATE) = 2010 AND MONTH(SCOREDATE) = 1 ORDER BY SCORE ASC) AS SubQ SELECT MIN(SubQ.SCORE) FROM (SELECT TOP 45 PERCENT SCORE FROM SCORES WHERE YEAR(SCOREDATE) = 2010 AND MONTH(SCOREDATE) = 1 ORDER BY SCORE DESC) AS SubQ
但是我无法弄清楚如何获得所有月份的表格。
| Date | Average | 45% | 55% | + -----------+---------+-----+-----+ | 01/01/2010 | 13 | 11 | 15 | | 02/01/2010 | 10 | 8 | 12 | | 03/01/2010 | 5 | 4 | 10 | ... | 16/03/2010 | 7 | 7 | 9 |
此刻,我将不得不把这些加载到我的应用程序中,然后自己计算这些数字。或运行大量的单个查询并整理结果。
ew。这是一个真正的脑筋急转弯。首先,我用于测试的表架构为:
Create Table Scores ( Id int not null identity(1,1) primary key clustered , [Date] datetime not null , Score int not null )
现在,首先,我在SQL 2008中使用CTE计算值以检查答案,然后构建了一个可以在SQL 2000中使用的解决方案。因此,在SQL 2008中,我们执行以下操作:
;With SummaryStatistics As ( Select Year([Date]) As YearNum , Month([Date]) As MonthNum , Min(Score) As MinScore , Max(Score) As MaxScore , Avg(Score) As AvgScore From Scores Group By Month([Date]), Year([Date]) ) , Percentiles As ( Select Year([Date]) As YearNum , Month([Date]) As MonthNum , Score , NTile( 100 ) Over ( Partition By Month([Date]), Year([Date]) Order By Score ) As Percentile From Scores ) , ReportedPercentiles As ( Select YearNum, MonthNum , Min(Case When Percentile = 45 Then Score End) As Percentile45 , Min(Case When Percentile = 55 Then Score End) As Percentile55 From Percentiles Where Percentile In(45,55) Group By YearNum, MonthNum ) Select SS.YearNum, SS.MonthNum , SS.MinScore, SS.MaxScore, SS.AvgScore , RP.Percentile45, RP.Percentile55 From SummaryStatistics As SS Join ReportedPercentiles As RP On RP.YearNum = SS.YearNum And RP.MonthNum = SS.MonthNum Order By SS.YearNum, SS.MonthNum
现在是一个SQL 2000解决方案。本质上,诀窍是使用几个临时表来计算分数的出现。
If object_id('tempdb..#Working') is not null DROP TABLE #Working GO Create Table #Working ( YearNum int not null , MonthNum int not null , Score int not null , Occurances int not null , Constraint PK_#Working Primary Key Clustered ( MonthNum, YearNum, Score ) ) GO Insert #Working(MonthNum, YearNum, Score, Occurances) Select Month([Date]), Year([Date]), Score, Count(*) From Scores Group By Month([Date]), Year([Date]), Score GO If object_id('tempdb..#SummaryStatistics') is not null DROP TABLE #SummaryStatistics GO Create Table #SummaryStatistics ( MonthNum int not null , YearNum int not null , Score int not null , Occurances int not null , CumulativeTotal int not null , Percentile float null , Constraint PK_#SummaryStatistics Primary Key Clustered ( MonthNum, YearNum, Score ) ) GO Insert #SummaryStatistics(YearNum, MonthNum, Score, Occurances, CumulativeTotal) Select W2.YearNum, W2.MonthNum, W2.Score, W2.Occurances, Sum(W1.Occurances)-W2.Occurances From #Working As W1 Join #Working As W2 On W2.YearNum = W1.YearNum And W2.MonthNum = W1.MonthNum Where W1.Score <= W2.Score Group By W2.YearNum, W2.MonthNum, W2.Score, W2.Occurances Update #SummaryStatistics Set Percentile = SS.CumulativeTotal * 100.0 / MonthTotal.Total From #SummaryStatistics As SS Join ( Select SS1.YearNum, SS1.MonthNum, Max(SS1.CumulativeTotal) As Total From #SummaryStatistics As SS1 Group By SS1.YearNum, SS1.MonthNum ) As MonthTotal On MonthTotal.YearNum = SS.YearNum And MonthTotal.MonthNum = SS.MonthNum Select GeneralStats.*, Percentiles.Percentile45, Percentiles.Percentile55 From ( Select Year(S1.[Date]) As YearNum , Month(S1.[Date]) As MonthNum , Min(S1.Score) As MinScore , Max(S1.Score) As MaxScore , Avg(S1.Score) As AvgScore From Scores As S1 Group By Month(S1.[Date]), Year(S1.[Date]) ) As GeneralStats Join ( Select SS1.YearNum, SS1.MonthNum , Min(Case When SS1.Percentile >= 45 Then Score End) As Percentile45 , Min(Case When SS1.Percentile >= 55 Then Score End) As Percentile55 From #SummaryStatistics As SS1 Group By SS1.YearNum, SS1.MonthNum ) As Percentiles On Percentiles.YearNum = GeneralStats.YearNum And Percentiles.MonthNum = GeneralStats.MonthNum