[英]How can i optimize this query? I am using sql server 2008
I have this SQL query which is valid but always times out. 我有此SQL查询,但有效,但总是超时。
CREATE PROCEDURE Sibm_getstudentdivisionattendancereport2 (
@course_id INT,
--@Subject_Id int,
@academic_year INT,
@division_id INT,
@semister_id INT,
@fromdate1 DATETIME,
@todate1 DATETIME)
AS
BEGIN
DECLARE @fromdate VARCHAR(100)
DECLARE @todate VARCHAR(100)
SET @fromdate=CONVERT(VARCHAR(10), @fromdate1, 105)
SET @todate=CONVERT(VARCHAR(10), @todate1, 105)
CREATE TABLE #getstudentmarks
(
id INT NOT NULL,
roll_no VARCHAR(100),
stud_id INT,
stud_name VARCHAR(200),
stud_last_name VARCHAR(200),
subject_name VARCHAR(200),
marks INT,
student_id INT,
division_id INT,
division VARCHAR(50),
attended VARCHAR(12),
exempted VARCHAR(12),
total_attendance VARCHAR(12),
attendancepercentage VARCHAR(30),
subject_id INT
)
CREATE TABLE #getstudentmarks1
(
id INT IDENTITY(1, 1) NOT NULL,
roll_no VARCHAR(100),
stud_id INT,
stud_name VARCHAR(200),
stud_last_name VARCHAR(200),
subject_name VARCHAR(200),
marks INT,
student_id INT,
division_id INT,
division VARCHAR(50),
attended VARCHAR(12),
exempted VARCHAR(12),
total_attendance VARCHAR(12),
attendancepercentage VARCHAR(30),
subject_id INT
)
CREATE TABLE #divisionlist
(
division_id INT
)
CREATE TABLE #getstudent_attended
(
id INT IDENTITY(1, 1) NOT NULL,
student_id INT,
exempted VARCHAR(12),
attended VARCHAR(12)
)
DECLARE @Total_Lectures INT
DECLARE @Student_Id INT
DECLARE @TotalConductedLecture INT
DECLARE @TotalExempted INT
INSERT INTO #getstudentmarks1
(roll_no,
student_id,
stud_name,
stud_last_name)
SELECT DISTINCT( SA.roll_no ),
SA.student_id AS id,
SR.first_name,
SR.last_name
FROM tblstudent_academic_record SA,
tblstudent_record SR
WHERE SR.student_id = SA.student_id
AND SR.student_id IN (SELECT SAR.student_id
FROM tblstudent_academic_record SAR
INNER JOIN tblcoursesemester_subject_student
CSS
ON SAR.student_id = CSS.student_id
AND SAR.current_record = 1
AND SAR.course_id = @course_id
AND
SAR.semister_id = @semister_id
AND
SAR.division_id = @division_id
AND
SAR.academic_year = @academic_year)
CREATE TABLE #temp
(
id INT,
subject_name VARCHAR(100)
)
DECLARE @Master_Id INT
SET @Master_Id = 0
IF EXISTS(SELECT *
FROM tblcoursesemester_main
WHERE academic_year = @Academic_Year
AND course_id = @Course_Id
AND semester_id = @semister_id)
BEGIN
SET @Master_Id = (SELECT TOP 1 cs_id
FROM tblcoursesemester_main
WHERE academic_year = @Academic_Year
AND course_id = @Course_Id
AND semester_id = @semister_id)
END
INSERT INTO #temp
SELECT id,
subject_name
FROM tblsubject
WHERE id IN (SELECT subject_id
FROM tblcoursesemester_subject
WHERE is_archieve IS NULL
AND cs_id = @Master_Id)
AND isarchive IS NULL
ORDER BY subject_name
DECLARE @tempid INT
DECLARE @sub VARCHAR(max)
DECLARE c1 CURSOR FOR
SELECT student_id
FROM #getstudentmarks1
OPEN c1
FETCH next FROM c1 INTO @Student_Id
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE c2 CURSOR FOR
SELECT id
FROM #temp
OPEN c2
FETCH next FROM c2 INTO @tempid
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE #getstudentmarks1
SET subject_name = (SELECT subject_name
FROM #temp
WHERE id = @tempid),
subject_id = @tempid
WHERE student_id = @Student_Id
FETCH next FROM c2 INTO @tempid
END
CLOSE c2
DEALLOCATE c2
FETCH next FROM c1 INTO @Student_Id
END
CLOSE c1
DEALLOCATE c1
--select * from #TEMP
--SET IDENTITY_INSERT #GetStudentMarks1 ON
INSERT INTO #getstudentmarks
(id,
roll_no,
stud_id,
stud_name,
stud_last_name,
subject_name,
marks,
student_id,
division_id,
division,
attended,
exempted,
total_attendance,
attendancepercentage,
subject_id)
SELECT #getstudentmarks1.id,
roll_no,
stud_id,
stud_name,
stud_last_name,
#temp.subject_name,
marks,
student_id,
division_id,
division,
attended,
exempted,
total_attendance,
attendancepercentage,
#temp.id
FROM #getstudentmarks1
CROSS JOIN #temp
-- select * from #GetStudentMarks cross join #TEMP
--SET IDENTITY_INSERT #GetStudentMarks1 OFF
--select * from #GetStudentMarks
---------calculate percentage-------------------
INSERT INTO #divisionlist
SELECT divisionid
FROM tblschedulemaster
WHERE academicyear = @academic_year
AND courseid = @Course_Id
AND semesterid = @Semister_Id
DECLARE @subject_id INT
DECLARE c1 CURSOR FOR
SELECT student_id
FROM #getstudentmarks
OPEN c1
FETCH next FROM c1 INTO @Student_Id
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE c3 CURSOR FOR
SELECT subject_id
FROM #getstudentmarks
OPEN c3
FETCH next FROM c3 INTO @subject_id
WHILE @@FETCH_STATUS = 0
BEGIN
-- GET TOTAL LECTURES OF EACH STUDENT
SELECT @Total_Lectures = Count([id])
FROM tblfacultyschedule
WHERE subjectid = @subject_id
AND sch_mas_id IN (SELECT [id]
FROM tblschedulemaster
WHERE academicyear = @academic_year
AND courseid = @Course_Id
AND semesterid = @Semister_Id
AND divisionid IN (
-- Changed Divisions list Query Starts
SELECT
divisionid
FROM
tblschedulemaster
WHERE
id IN (SELECT DISTINCT
sch_mas_id
FROM
tblfacultyschedule
WHERE
[date] >= @fromdate
AND [date] <= @todate
AND
id IN (SELECT DISTINCT
schedule_id
FROM
tblstudentattendence
WHERE
student_id = @Student_Id
AND schedule_id IN (SELECT
id
FROM
tblfacultyschedule
WHERE
subjectid =
@subject_id
AND
sch_mas_id IN(SELECT
id
FROM
tblschedulemaster
WHERE
academicyear =
@academic_year
AND
courseid =
@Course_Id
AND
semesterid
=
@Semister_Id))
))
-- Changed Divisions list Query Ends
))
AND COALESCE(other_activity, '') NOT LIKE '%LUNCH%'
--print 'subject id'
--print @subject_id
--print 'totol att'
--print @Total_Lectures
-- Total Conducted Lectures
SET @TotalConductedLecture =
(SELECT
COALESCE(Count(is_attended), 0) AS Attended
FROM tblstudentattendence
WHERE student_id = @Student_id
AND is_attended = 'YES'
AND
schedule_id IN (SELECT [id]
FROM
tblfacultyschedule
WHERE
[date] >= @fromdate
AND [date] <= @todate
AND subjectid = @subject_id
AND
sch_mas_id IN (SELECT [id]
FROM
tblschedulemaster
WHERE
academicyear = @academic_year
AND courseid = @course_id
AND semesterid = @semister_id
AND divisionid IN (SELECT
division_id
FROM
#divisionlist))
AND
COALESCE(other_activity, '')
NOT
LIKE
'%LUNCH%'
AND
subjectid IN (SELECT DISTINCT
subject_id
FROM
tblcoursesemester_subject
WHERE
cs_subject_id IN (SELECT
cs_subject_id
FROM
tblcoursesemester_subject_student
WHERE
cs_subject_id IN (SELECT
cs_subject_id
FROM
tblcoursesemester_subject
WHERE
cs_id IN (SELECT cs_id
FROM
tblcoursesemester_main
WHERE
academic_year = @academic_year
AND course_id = @course_id
AND semester_id = @semister_id
)
AND is_archieve IS NULL)
AND student_id = @Student_id
AND is_archieve IS NULL)
AND is_archieve IS NULL)))
--print 'attended'
-- print @TotalConductedLecture
-- NOW COUNT Exempted LECTURES
SET @TotalExempted=
(SELECT COALESCE(Count(is_attended), 0) AS
Attended
FROM tblstudentattendence
WHERE student_id = @Student_id
AND is_attended = 'EXEMPTED'
AND schedule_id IN (SELECT [id]
FROM
tblfacultyschedule
WHERE
[date] >= @fromdate
AND [date] <= @todate
AND subjectid =
@subject_id
AND sch_mas_id IN (SELECT
[id]
FROM
tblschedulemaster
WHERE
academicyear =
@academic_year
AND
courseid =
@course_id
AND
semesterid =
@semister_id
AND
divisionid IN (
SELECT
division_id
FROM
#divisionlist))
AND
COALESCE(other_activity, '') NOT
LIKE
'%LUNCH%'
AND
subjectid IN (SELECT DISTINCT
subject_id
FROM
tblcoursesemester_subject
WHERE
cs_subject_id IN (SELECT
cs_subject_id
FROM
tblcoursesemester_subject_student
WHERE
cs_subject_id IN (SELECT
cs_subject_id
FROM
tblcoursesemester_subject
WHERE
cs_id IN (SELECT cs_id
FROM
tblcoursesemester_main
WHERE
academic_year = @academic_year
AND course_id = @course_id
AND semester_id = @semister_id
)
AND is_archieve IS NULL)
AND student_id = @Student_id
AND is_archieve IS NULL)
AND is_archieve IS NULL)))
-- print 'not attended'
-- print @TotalExempted
UPDATE #getstudentmarks
SET #getstudentmarks.total_attendance = @Total_Lectures,
#getstudentmarks.attended = @TotalConductedLecture,
#getstudentmarks.exempted = @TotalExempted
WHERE student_id = @Student_Id
AND subject_id = @subject_id
FETCH next FROM c3 INTO @subject_id
END
CLOSE c3
DEALLOCATE c3
FETCH next FROM c1 INTO @Student_Id
END
CLOSE c1
DEALLOCATE c1
-- CURSOR ENDS
--select * from #GetStudentMarks
UPDATE #getstudentmarks
SET #getstudentmarks.division = tbldivision.division
FROM #getstudentmarks,
tbldivision
WHERE #getstudentmarks.division_id = tbldivision.division_id
UPDATE #getstudentmarks
SET #getstudentmarks.attended = #getstudent_attended.attended
FROM #getstudentmarks,
#getstudent_attended
WHERE #getstudentmarks.student_id = #getstudent_attended.student_id
UPDATE #getstudentmarks
SET #getstudentmarks.exempted = #getstudent_attended.exempted
FROM #getstudentmarks,
#getstudent_attended
WHERE #getstudentmarks.student_id = #getstudent_attended.student_id
UPDATE #getstudentmarks
SET attended = Isnull(attended, '0')
UPDATE #getstudentmarks
SET exempted = Isnull(exempted, '0')
UPDATE #getstudentmarks
SET total_attendance = Isnull(total_attendance, '0')
--UPDATE #GetStudentMarks SET #GetStudentMarks.AttendancePercentage=CAST(CAST((CAST(#GetStudentMarks.Attended AS NUMERIC(32,2)) * 100)/CAST(#GetStudentMarks.Total_Attendance AS NUMERIC(32,2)) AS NUMERIC(32,2)) AS VARCHAR(30))
--WHERE #GetStudentMarks.Total_Attendance <> '0'
UPDATE #getstudentmarks
SET
#getstudentmarks.attendancepercentage = Cast(
Cast(
Cast(( Cast(#getstudentmarks.attended AS NUMERIC(32, 2)) * 100 ) +
(
Cast(
#getstudentmarks.exempted AS
NUMERIC(32, 2)) *
100 ) AS NUMERIC(32, 2)) /
Cast
(
#getstudentmarks.total_attendance AS
NUMERIC(
32, 2)) AS NUMERIC(32, 2)) AS
VARCHAR
(30))
WHERE #getstudentmarks.total_attendance <> '0'
--+ '' + '%'
UPDATE #getstudentmarks
SET attendancepercentage = Isnull(attendancepercentage, '0.00')
--UPDATE #GetStudentMarks SET #GetStudentMarks.AttendancePercentage = '0 %' WHERE #GetStudentMarks.AttendancePercentage IS NULL
-------------end calculation---------------------
DECLARE @Roll_No VARCHAR(20),
@Stud_Id VARCHAR(20),
@Stud_Name VARCHAR(200),
@Subject_Name VARCHAR(200),
@Stud_Last_Name VARCHAR(200),
@AttendancePercentage VARCHAR(200)
-- select * from #GetStudentMarks
DECLARE @cntColm INT
SELECT @cntColm = Count(roll_no)
FROM #getstudentmarks
GROUP BY roll_no
CREATE TABLE #subject
(
sub_name VARCHAR(200)
)
INSERT INTO #subject
(sub_name)
SELECT DISTINCT( subject_name )
FROM #getstudentmarks
--print @cntColm
CREATE TABLE #getmarkssheet
(
student_id VARCHAR(100),
roll_no VARCHAR(100),
student_name VARCHAR(200)
)
--select * from #Subject
--------------- Cursor To add Columns As a Subject Name-------------------
-- print'text'
DECLARE @Stubject VARCHAR(max)
DECLARE curaddcol CURSOR FOR
SELECT sub_name
FROM #subject
OPEN curaddcol
FETCH next FROM curaddcol INTO @Stubject
WHILE @@FETCH_STATUS = 0
BEGIN
--print @Stubject
DECLARE @column VARCHAR(max)
SELECT @column = Replace(@Stubject, '&', '')
SELECT @column = Replace(@column, 'and', '')
SELECT @column = Replace(@column, '.', '')
SELECT @column = Replace(@column, ',', '')
SELECT @column = Replace(@column, ' ', '')
SELECT @column = Replace(@column, '-', '')
SELECT @column = Replace(@column, '(', '')
SELECT @column = Replace(@column, ')', '')
SELECT @column = Replace(@column, '/', '')
SELECT @column = Replace(@column, '//', '')
SELECT @column = Replace(@column, '\', '')
SELECT @column = Replace(@column, ':', '')
--print 'columnname' + @column
IF( @column <> '' )
BEGIN
EXEC('ALTER TABLE #GetMarksSheet ADD ' + @column +
' VARCHAR(max)')
--print @column
END
SET @cntColm=@cntColm - 1
FETCH next FROM curaddcol INTO @Stubject
END
---------------------------- Cursor Ends------------------------------------------
DECLARE cursubject CURSOR FOR
SELECT roll_no,
student_id,
stud_name,
stud_last_name,
subject_name,
attendancepercentage
FROM #getstudentmarks
OPEN cursubject
FETCH next FROM cursubject INTO @Roll_No, @Stud_Id, @Stud_Name,
@Stud_Last_Name, @Subject_Name, @AttendancePercentage
-- while @cntColm >0
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @ColName VARCHAR(max)
SELECT @ColName = Replace(@Subject_Name, '&', '')
SELECT @ColName = Replace(@ColName, 'and', '')
SELECT @ColName = Replace(@ColName, ',', '')
SELECT @ColName = Replace(@ColName, '.', '')
SELECT @ColName = Replace(@ColName, ' ', '')
SELECT @ColName = Replace(@ColName, '-', '')
SELECT @ColName = Replace(@ColName, '(', '')
SELECT @ColName = Replace(@ColName, ')', '')
SELECT @ColName = Replace(@ColName, '/', '')
SELECT @ColName = Replace(@ColName, '//', '')
SELECT @ColName = Replace(@ColName, '\', '')
SELECT @ColName = Replace(@ColName, ':', '')
DECLARE @MarkInPer VARCHAR(max)
SET @MarkInPer=Cast(@AttendancePercentage AS VARCHAR(max))
IF NOT EXISTS (SELECT student_id
FROM #getmarkssheet
WHERE student_id = @Stud_Id)
BEGIN
DECLARE @FullName VARCHAR(400)
--print @AttendancePercentage
--print @ColName+'----' +Cast(@MarkInPer as varchar(max)) +'----'
-- select @MarkInPer=COALESCE(@MarkInPer,0)
-- print @Roll_No + 'roll num'
EXEC('insert into #GetMarksSheet(Student_Id,'+ @ColName +
') values ('+
@Stud_Id +','+@MarkInPer + ')')
-- print @Stud_Name
UPDATE #getmarkssheet
SET student_name = @Stud_Name
WHERE student_id = @Stud_Id
--exec('UPDATE #GetMarksSheet SET Student_Name='+@Stud_Name +' where Roll_No='+@Roll_No)
END
ELSE
EXEC('UPDATE #GetMarksSheet SET '+ @ColName +' = '+@MarkInPer +
' where Student_Id='+@Stud_Id)
SET @cntColm=@cntColm - 1
FETCH next FROM cursubject INTO @Roll_No, @Stud_Id, @Stud_Name,
@Stud_Last_Name, @Subject_Name, @AttendancePercentage
END
SELECT *
FROM #getmarkssheet
END
Ouch. 哎哟。 Do it without temp tables and try it in one statement. 在没有临时表的情况下执行此操作,然后在一条语句中进行尝试。 It looks doable. 看起来可行。
Your approach kills the query optimizer's ability to optimize because you give it detailed steps including a (OUCH) cursoer which means single processor loop behavior as you DEMAND it. 您的方法破坏了查询优化器的优化能力,因为您给了它详细的步骤,包括(OUCH)光标,这意味着在您要求时单处理器循环行为。
This is NOT sql, this is a perversion - sql deals with sets. 这不是sql,这是一个变态-sql处理集合。
I am sure you CAN describ the result in one statement, without the use of temporary tables, and the result may surprise you performance wise ;) 我确信您可以在不使用临时表的情况下用一个语句描述结果,并且结果可能会使您对性能感到惊讶;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.