SELECT TOP 1 @CurrentStudentID = StudentID
FROM Courses WITH (NOLOCK)
WHERE Courses.CourseID = @CourseID
ORDER BY StudentID
-- Loop through all the students and find if he/she is registered for more than one course.
WHILE (@@ROWCOUNT > 0 AND @CurrentStudentID IS NOT NULL)
BEGIN
-- Select all other courses student is currently registered in.
IF @@ROWCOUNT > 0
BEGIN
-- return required information
END
ELSE
BEGIN
-- Perform some operations
END
-- Select the next registered student
SELECT TOP 1 @CurrentStudentID = StudentID
FROM Courses WITH (NOLOCK)
WHERE Courses.CourseID = @CourseID AND
Courses.StudentID > @CurrentStudentID
ORDER BY StudentID
END
有人可以在这里帮助我的逻辑吗?我写了一个存储过程,以确定一门课程的学生目前是否正在从同一所学校学习其他课程。
如果学生人数众多,我特别担心两个SELECT查询和while循环的表现。我觉得我这样做的感觉非常人为。我确信有更好的方法可以做到这一点。
我已对此存储过程进行了SQL分析,对于单个调用,其持续时间范围为0 - 60 ms。我不明白为什么相同的存储过程的执行时间是如此随机和不一致。
感谢任何帮助。我只有1年以上的SQL Server 2008经验。
提前致谢。
答案 0 :(得分:1)
正如我所提到的,SQL是一种基于集合的理论语言。换句话说,它与数据集是半关系的,允许在数据组之间进行有效的比较。诸如C ++或Java之类的“较低”语言不能维护如此大的数据集,因为它们是基于光标(逐行)的语言。
此定义的高级别,重点是将您的数据视为EXCEL
张。您有预定义的列,例如CourseID
和StudentID
,其他列中的信息依赖于这些值(CourseID
1:1 Course_Name)和一些重复的信息(CourseID)可以有多个学生)。
真正的规范化包括删除相互依赖的列,但现在不用担心。主要关注的是对业务有意义的事情。您的表格已为其课程和学生识别列。因此,如果这些值没有冲突的相互依赖的值,则不需要使用游标。
SELECT StudentID, COUNT(COURSEID) AS CLASS_NUM
FROM COURSES
GROUP BY StudentID
HAVING COUNT(COURSEID) > 1
GROUP BY
从列出的列中返回不同的值集,展平其他行并允许聚合函数,如COUNT()
。 (注意:NULLS
不计入COUNT()
。使用ISNULL
功能)
您还没有限制列表,但是您获得了相同的结果。在SQL展平行之后,如果需要,可以使用HAVING
子句进一步限制GROUP BY
的结果集。
绝对比光标快。 :)
现在,如果您的表格包含不同学期和年份的学生,您可以考虑将其添加到GROUP BY
,以便在GROUP BY
(StudentID
和{{ 1}})
另外,请回想一下Year
语句在SELECT
和GROUP BY
子句之后进行LOGICALLY读取,因此HAVING
语句中列出的任何列都必须出现在{{1}中或者具有聚合函数。