【问题标题】:SQL Server performance issue with while loopsSQL Server 的 while 循环性能问题
【发布时间】:2016-01-04 08:06:02
【问题描述】:

我只需要关于如何加快代码速度的建议。我应该指望每年的基数,一些学生的成绩如何提高并以百分比计算。另外请记住,我每年大约有 100k-150k 条记录。

基本上最终结果是这样的,所以在 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 行当前成绩,然后我不断更新该行直到它完全填充。

我确实知道这很糟糕,但最后这就是为什么我在这里学习更好的方法来实现这一点。

提前谢谢你!

【问题讨论】:

  • 分享输入和想要的输出,你会得到不循环的答案
  • 您应该了解GROUP BY 和子查询。
  • 你只会有A、B和C等级?
  • 是的,锻炼只是让 A、B、C 变得简单
  • Sql-server 不喜欢或不喜欢 while 循环。 #TempTable 的声明在哪里?它有索引吗?您正在扫描和汇总多少数据? While 循环条件中的变量退出它们的 SET 命令在哪里?

标签: sql sql-server performance tsql while-loop


【解决方案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 服务器执行的窗口函数。

【讨论】:

    猜你喜欢
    • 2020-08-26
    • 2021-07-31
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 2011-06-19
    • 2012-05-21
    相关资源
    最近更新 更多