2015-10-07 115 views
1

我只需要关于如何加快我的代码的建议。我应该指望每年的基数,一些学生的成绩如何提高并以百分比计算。另外请记住,我每年有大约10万-15万条记录。While循环的SQL Server性能问题

基本上最终的结果看起来像这样,所以在20150131年底,2%的学生已经达到了A级,并且达到了B级,等等。

Grade Date  B C 
    A  20150131 2% 3% 
    B  20150131 88% 85% 
    C  20150131 10% 12% 
    A  20140131 2% 3% 
    B  20140131 88% 85% 
    C  20140131 10% 12% 
    A  20130131 2% 3% 
    B  20130131 88% 85% 
    C  20130131 10% 12% 

输入看起来是这样的。关于学生只是信息以及他对某些日期评分

Student Date Grade 
    1  20150131 A 
    2  20150131 C 
    3  20150131 A 
    1  20140131 B 
    2  20140131 B 
    3  20140131 A 

我的代码如下所示:

WHILE @StartDateInt > @PeriodSpan 
BEGIN 
while @y <= @CategoriesCount 
BEGIN 

    set @CurrentGr = (Select Grade from #Categories where RowID = @y) 
    set @CurrentGrCount = (Select COUNT(Students) from #TempTable where Period = @PeriodSpan and Grade = @CurrentGr)  
    set @DefaultCurrentGr = (Select Grade from #Categories where RowID = @y) 

    insert into Grade_MTRX (Student, Period, Grades_B, SessionID)    
    select temp1.Grade, @PeriodNextSpan as Period, COUNT(Grades_B)/@CurrentGrCount as 'Grades_B', @SessionID    
    from #TempTable temp1 
    join #TempTable temp2 on temp1.Student = temp2.Student and temp1.Period + 10000 = temp2.Period 
    where temp1.Grade = @CurrentGr and temp2.Grade = 'C' and temp1.Period = @PeriodSpan  
    group by temp1.Grade, temp1.Period 

    update Grade_MTRX set Grades_C = (
    select COUNT(Grades_C)/@CurrentGrCount 
    from #TempTable 
    where Grade = 'C' and Period = @PeriodNextSpan) 
    where Category = @CurrentGr and Period = @PeriodNextSpan 

end 
end 

我了解SQL Server不像while循环,据我了解它会杀死它的性能......但我在while循环内使用while ......历经多年,因为每个年级,并只计算他们和...首先,我插入当前成绩的1行,然后我不断更新该行,直到其完全填充。

我明白这确实很糟糕,但最终这就是为什么我在这里学习更好的方法来实现这一目标。

预先感谢您!

+0

分享输入和期望的输出,你将得到没有循环的答案 – lad2025

+0

你应该了解'GROUP BY'和子查询。 – 2015-10-07 07:40:16

+0

你将只有A,B和C等级? –

回答

1

每年150,000条记录真的没什么。比方说,你有这个成绩表:

CREATE TABLE Grade(
student_id INT, 
date INT, 
grade CHAR); 

有了这个信息:

student_id date grade 
    1  2013 A 
    1  2014 A 
    1  2015 B 
    2  2013 B 
    2  2014 A 
    2  2015 C 
    3  2013 C 
    3  2014 A 
    3  2015 B 

然后,如果你只是运行像一个查询:

SELECT this_year.date, last_year.grade AS last_year, this_year.grade AS this_year, COUNT(*) AS total, 
(100.0 * COUNT(*))/(SELECT COUNT(*) FROM Grade WHERE date = this_year.date) AS percent 
FROM Grade AS this_year 
    INNER JOIN Grade AS last_year ON this_year.date = last_year.date + 1 
    AND this_year.student_id = last_year.student_id 
GROUP BY this_year.date, this_year.grade, last_year.grade 
ORDER BY 1, 2, 3; 

你结束了这些结果:

date | last_year | this_year | total |  percent  
------+-----------+-----------+-------+--------------------- 
2014 | A   | A   |  1 | 33.3333333333333333 
2014 | B   | A   |  1 | 33.3333333333333333 
2014 | C   | A   |  1 | 33.3333333333333333 
2015 | A   | B   |  2 | 66.6666666666666667 
2015 | A   | C   |  1 | 33.3333333333333333 
(5 rows) 

有几毫米在使用这种查询的数据行上不应该有任何真正的麻烦。甚至数千万行。但是,如果您需要更快的速度,那么请查看您可以使用Postgres,Oracle和MSSQL服务器执行的窗口功能。

+0

谢谢你指点我朝着正确的方向! – Veljko89