我有下面的查询 - 这有效,但在MSSMS中运行大约需要80秒。我想知道它是否可以提高效率吗?
下面将进行解释。
SELECT A.courseid, A.studentid, attendanceStatus, lessonDate,
(SELECT top 1 SnoozeFrom FROM [tblConsecutiveSnooze] C
WHERE A.courseID = C.courseID AND A.StudentID = C.StudentID
ORDER BY SnoozeFrom DESC ) AS latestSnooze ,
(SELECT top 1 SnoozeTimes FROM [tblConsecutiveSnooze] D
WHERE A.courseID = D.courseID AND A.StudentID = D.StudentID
ORDER BY SnoozeFrom DESC ) AS snoozeTimes
FROM [tblStudentAttendance] A INNER JOIN tblcourses
ON A.courseID = tblcourses.courseID
WHERE [lessonDate] > getdate()-21
AND EXISTS (SELECT * FROM tblstudentCourses B WHERE A.courseID = B.courseID
AND B.[DateLeft] IS NULL AND A.StudentID = B.StudentID)
ORDER BY courseid , studentID, [lessonDate]
所以我正在做的是尝试访问所有学生出勤记录(来自tblStudentAttendance),在过去的21天内,我已经确认(通过EXISTS)该学生确实仍然注册了该课程。
这两个子SELECT查询可以合并为一个,但这对查询的运行时间没有影响。
似乎对运行时间有很大影响的是EXISTS条件。所以任何建议都值得赞赏。
更新
Sql Plan: http://199.127.217.23/mm.sqlplan
索引:
答案 0 :(得分:1)
如果查看发布的执行计划,您会发现添加缺失的索引可以将查询性能提高多达33%。您可以尝试将以下非聚集索引添加到tblStudentCourses表。您可以将索引名称更改为适合您的名称。
USE [hvps453_datab2]
GO
CREATE NONCLUSTERED INDEX [NC_tblStuddentCourses_DL_SI_CI]
ON [dbo].[tblStudentCourses] ([DateLeft])
INCLUDE ([studentID],[courseId])
GO
答案 1 :(得分:0)
带有行号的派生表如何找到最新的SnoozeFrom记录?或者,也可以使用CTE。
SELECT A.courseid
, A.studentid
, attendanceStatus
, lessonDate
, ConsecSnooze.SnoozeFrom AS latestSnooze
, ConsecSnooze.SnoozeTimes AS snoozeTimes
FROM [tblStudentAttendance] A
INNER JOIN tblcourses
ON A.courseID = tblcourses.courseID
LEFT JOIN (
SELECT SnoozeFrom
, SnoozeTimes
, C.courseID
, C.StudentID
, ROW_NUMBER() OVER (PARTITION BY C.CourseID, C.StudentID ORDER BY SnoozeFrom DESC) AS RowNum
FROM [tblConsecutiveSnooze] C
) as ConsecSnooze ON ConsecSnooze.courseID = A.courseID
AND ConsecSnooze.StudentID = A.studentID
AND ConsecSnooze.RowNum = 1
WHERE [lessonDate] > getdate() - 21
AND EXISTS (
SELECT *
FROM tblstudentCourses B
WHERE A.courseID = B.courseID
AND B.[DateLeft] IS NULL
AND A.StudentID = B.StudentID
)
ORDER BY courseid
, studentID
, [lessonDate]
答案 2 :(得分:0)
如果您访问tblConsecutiveSnooze
的主要方式是CourseID
和StudentID
,那么我高度建议您将PK更改为非群集并添加CourseID, StudentID
上的聚集索引。这远远优于仅添加非聚簇索引并将聚簇PK保留在id
上。此外,如果没有FK,那么您甚至可能不需要id
列(切换到CourseID, StudentID
没有意义)。虽然我是代理键的支持者,但不是每个表都需要它们!
我还建议您停止命名列id
。列名在其中存在的每个表中应该相同,包括其基表。