Sql server 如何优化此查询?我正在使用SQLServer2008

Sql server 如何优化此查询?我正在使用SQLServer2008,sql-server,Sql Server,我有一个有效但总是超时的SQL查询 CREATE PROCEDURE Sibm_getstudentdivisionattendancereport2 ( @course_id INT, --@Subject_Id int, @academic_year INT, @division_id INT, @semister_id INT, @fromdate

我有一个有效但总是超时的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 cursoer,这意味着单处理器循环行为,正如您所要求的那样

这不是sql,这是一种反常现象—sql处理集合


我相信您可以在一个语句中描述结果,而无需使用临时表,结果可能会让您在性能方面感到惊讶

太长了,信息太少了。也许你应该创建一个小型的、独立的复制程序。你能和我们分享一下执行计划吗?使用这些信息诊断SQL性能问题要容易得多。我需要计算每个科目的学生出勤率(百分比)