需要查询优化

问题描述 投票:0回答:2

需要优化我的sql查询以提高性能。下面是查询

 SELECT 
      (
      CASE
        WHEN (SELECT NVL(TO_CHAR(PREFS.VALUE), '0')
          FROM PREFS
          WHERE PREFS.SCHOOLID  = EV.SCHOOLID
          AND LOWER(PREFS.NAME) = 'att_calccntattothschenrthissch'
          AND PREFS.YEARID      = EV.YEARID
          AND PREFS.DCID        =
            (SELECT MIN(DCID)
            FROM PREFS PDUPS
            WHERE PDUPS.SCHOOLID  = EV.SCHOOLID
            AND LOWER(PDUPS.NAME) = 'att_calccntattothschenrthissch'
            AND PDUPS.YEARID      = EV.YEARID
            ) )                   = '1'
        THEN
          (SELECT COUNT(PER.PERIOD_NUMBER)
          FROM PERIOD PER,
            BELL_SCHEDULE_ITEMS BSI,
            CYCLE_DAY CY,
            CALENDAR_DAY CDSUB,
            CC CC,
            SECTION_MEETING SM,
            SECTIONS SEC
          WHERE CC.DATEENROLLED   <= CD.DATE_VALUE
          AND CD.DATE_VALUE        < CC.DATELEFT
          AND ABS( CC.SECTIONID )  = SM.SECTIONID
          AND SM.SECTIONID         = SEC.ID
          AND SEC.EXCLUDE_ADA      = 0
          AND SM.PERIOD_NUMBER     = PER.PERIOD_NUMBER
          AND SM.SCHOOLID          = PER.SCHOOLID
          AND SM.YEAR_ID           = PER.YEAR_ID
          AND BSI.PERIOD_ID        = PER.ID
          AND BSI.BELL_SCHEDULE_ID = CDSUB.BELL_SCHEDULE_ID
          AND ( (CDSUB.SCHOOLID    = EV.SCHOOLID
          AND BSI.ADA_CODE         = 1)
          OR (CDSUB.SCHOOLID      <> EV.SCHOOLID) )
          AND SM.CYCLE_DAY_LETTER  = CY.LETTER
          AND SM.SCHOOLID          = CY.SCHOOLID
          AND SM.YEAR_ID           = CY.YEAR_ID
          AND SM.YEAR_ID           = EV.YEARID
          AND CY.ID                = CDSUB.CYCLE_DAY_ID
          AND CDSUB.DATE_VALUE     = CD.DATE_VALUE
          AND CDSUB.INSESSION      = 1
          AND CC.STUDENTID         = EV.STUDENTID
          AND CC.DCID NOT         IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          )
        ELSE
          (SELECT COUNT(P.PERIOD_NUMBER)
          FROM CC CC,
            SECTION_MEETING SM,
            CYCLE_DAY CY,
            PERIOD P,
            BELL_SCHEDULE_ITEMS BSI,
            SECTIONS SEC
          WHERE CC.STUDENTID       = EV.STUDENTID
          AND CC.DATEENROLLED     <= CD.DATE_VALUE
          AND CC.DATELEFT          > CD.DATE_VALUE
          AND CY.ID                = CD.CYCLE_DAY_ID
          AND SM.SECTIONID         = ABS(CC.SECTIONID)
          AND SM.CYCLE_DAY_LETTER  = CY.LETTER
          AND SM.PERIOD_NUMBER     = P.PERIOD_NUMBER
          AND SM.SCHOOLID          = P.SCHOOLID
          AND SM.YEAR_ID           = P.YEAR_ID
          AND SM.YEAR_ID           = EV.YEARID
          AND SM.SECTIONID         = SEC.ID
          AND SEC.EXCLUDE_ADA      = 0
          AND BSI.BELL_SCHEDULE_ID = CD.BELL_SCHEDULE_ID
          AND BSI.ADA_CODE         = 1
          AND BSI.PERIOD_ID        = P.ID
          AND CC.DCID NOT         IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          )
      END) AS POTENTIAL_PERIODS_PRESENT,
      (
      CASE
        WHEN (SELECT NVL(TO_CHAR(PREFS.VALUE), '0')
          FROM PREFS
          WHERE PREFS.SCHOOLID  = EV.SCHOOLID
          AND LOWER(PREFS.NAME) = 'att_calccntattothschenrthissch'
          AND PREFS.YEARID      = EV.YEARID
          AND PREFS.DCID        =
            (SELECT MIN(DCID)
            FROM PREFS PDUPS
            WHERE PDUPS.SCHOOLID  = EV.SCHOOLID
            AND LOWER(PDUPS.NAME) = 'att_calccntattothschenrthissch'
            AND PDUPS.YEARID      = EV.YEARID
            ) )                   = '1'
        THEN NVL(
          (SELECT SUM(BSI.MINUTES_ATTENDED)
          FROM PERIOD PER,
            BELL_SCHEDULE_ITEMS BSI,
            CYCLE_DAY CY,
            CALENDAR_DAY CDSUB,
            CC CC,
            SECTION_MEETING SM,
            SECTIONS SEC
          WHERE CC.DATEENROLLED   <= CD.DATE_VALUE
          AND CD.DATE_VALUE        < CC.DATELEFT
          AND ABS( CC.SECTIONID )  = SM.SECTIONID
          AND SM.SECTIONID         = SEC.ID
          AND SEC.EXCLUDE_ADA      = 0
          AND SM.PERIOD_NUMBER     = PER.PERIOD_NUMBER
          AND SM.SCHOOLID          = PER.SCHOOLID
          AND SM.YEAR_ID           = PER.YEAR_ID
          AND BSI.PERIOD_ID        = PER.ID
          AND BSI.BELL_SCHEDULE_ID = CDSUB.BELL_SCHEDULE_ID
          AND ( (CDSUB.SCHOOLID    = EV.SCHOOLID
          AND BSI.ADA_CODE         = 1)
          OR (CDSUB.SCHOOLID      <> EV.SCHOOLID) )
          AND SM.CYCLE_DAY_LETTER  = CY.LETTER
          AND SM.SCHOOLID          = CY.SCHOOLID
          AND SM.YEAR_ID           = CY.YEAR_ID
          AND SM.YEAR_ID           = EV.YEARID
          AND CY.ID                = CDSUB.CYCLE_DAY_ID
          AND CDSUB.DATE_VALUE     = CD.DATE_VALUE
          AND CDSUB.INSESSION      = 1
          AND CC.STUDENTID         = EV.STUDENTID
          AND CC.DCID NOT         IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          ) ,0)
        ELSE NVL(
          (SELECT SUM(BSI.MINUTES_ATTENDED)
          FROM CC CC,
            SECTION_MEETING SM,
            CYCLE_DAY CY,
            PERIOD P,
            BELL_SCHEDULE_ITEMS BSI,
            SECTIONS SEC
          WHERE CC.STUDENTID       = EV.STUDENTID
          AND CC.DATEENROLLED     <= CD.DATE_VALUE
          AND CC.DATELEFT          > CD.DATE_VALUE
          AND CY.ID                = CD.CYCLE_DAY_ID
          AND SM.SECTIONID         = ABS(CC.SECTIONID)
          AND SM.CYCLE_DAY_LETTER  = CY.LETTER
          AND SM.PERIOD_NUMBER     = P.PERIOD_NUMBER
          AND SM.SCHOOLID          = P.SCHOOLID
          AND SM.YEAR_ID           = P.YEAR_ID
          AND SM.YEAR_ID           = EV.YEARID
          AND SM.SECTIONID         = SEC.ID
          AND SEC.EXCLUDE_ADA      = 0
          AND BSI.BELL_SCHEDULE_ID = CD.BELL_SCHEDULE_ID
          AND BSI.ADA_CODE         = 1
          AND BSI.PERIOD_ID        = P.ID
          AND CC.DCID NOT         IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          ) ,0)
      END) AS POTENTIAL_MINUTES_PRESENT,
      (
      CASE
        WHEN (SELECT NVL(TO_CHAR(PREFS.VALUE), '0')
          FROM PREFS
          WHERE PREFS.SCHOOLID  = EV.SCHOOLID
          AND LOWER(PREFS.NAME) = 'att_calccntattothschenrthissch'
          AND PREFS.YEARID      = EV.YEARID
          AND PREFS.DCID        =
            (SELECT MIN(DCID)
            FROM PREFS PDUPS
            WHERE PDUPS.SCHOOLID  = EV.SCHOOLID
            AND LOWER(PDUPS.NAME) = 'att_calccntattothschenrthissch'
            AND PDUPS.YEARID      = EV.YEARID
            ) )                   = '1'
        THEN
          (SELECT COUNT(*)
          FROM ATTENDANCE ATT,
            ATTENDANCE_CODE AC,
            CC CC,
            SECTIONS SEC,
            BELL_SCHEDULE_ITEMS BSI,
            CALENDAR_DAY CDSUB
          WHERE ATT.STUDENTID        = CC.STUDENTID
          AND CDSUB.DATE_VALUE       = CD.DATE_VALUE
          AND CDSUB.BELL_SCHEDULE_ID = BSI.BELL_SCHEDULE_ID
          AND BSI.PERIOD_ID          = ATT.PERIODID
          AND ( (CDSUB.SCHOOLID      = EV.SCHOOLID
          AND BSI.ADA_CODE           = 1)
          OR (CDSUB.SCHOOLID        <> EV.SCHOOLID) )
          AND ATT.CCID               = CC.ID
          AND ATT.ATTENDANCE_CODEID  = AC.ID
          AND CC.DATEENROLLED       <= ATT.ATT_DATE
          AND ATT.ATT_DATE           < CC.DATELEFT
          AND ATT.ATT_MODE_CODE      = 'ATT_ModeMeeting'
          AND AC.PRESENCE_STATUS_CD  = 'Absent'
          AND AC.CALCULATE_ADA_YN    = 1
          AND ABS(CC.SECTIONID)      = SEC.ID
          AND SEC.EXCLUDE_ADA        = 0
          AND ATT.STUDENTID          = EV.STUDENTID
          AND ATT.ATT_DATE           = CD.DATE_VALUE
          AND CC.DCID NOT           IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          )
        ELSE
          (SELECT COUNT(*)
          FROM ATTENDANCE ATT,
            ATTENDANCE_CODE AC,
            CC CC,
            SECTIONS SEC,
            BELL_SCHEDULE_ITEMS BSI
          WHERE ATT.STUDENTID       = CC.STUDENTID
          AND CD.BELL_SCHEDULE_ID   = BSI.BELL_SCHEDULE_ID
          AND BSI.PERIOD_ID         = ATT.PERIODID
          AND BSI.ADA_CODE          = 1
          AND ATT.CCID              = CC.ID
          AND ATT.ATTENDANCE_CODEID = AC.ID
          AND ATT.ATT_DATE         >= CC.DATEENROLLED
          AND ATT.ATT_DATE          < CC.DATELEFT
          AND ATT.ATT_MODE_CODE     = 'ATT_ModeMeeting'
          AND AC.PRESENCE_STATUS_CD = 'Absent'
          AND AC.CALCULATE_ADA_YN   = 1
          AND ABS(CC.SECTIONID)     = SEC.ID
          AND SEC.EXCLUDE_ADA       = 0
          AND ATT.STUDENTID         = EV.STUDENTID
          AND ATT.ATT_DATE          = CD.DATE_VALUE
          AND CC.DCID NOT          IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          )
      END) AS PERIODS_ABSENT,
      (
      CASE
        WHEN (SELECT NVL(TO_CHAR(PREFS.VALUE), '0')
          FROM PREFS
          WHERE PREFS.SCHOOLID  = EV.SCHOOLID
          AND LOWER(PREFS.NAME) = 'att_calccntattothschenrthissch'
          AND PREFS.YEARID      = EV.YEARID
          AND PREFS.DCID        =
            (SELECT MIN(DCID)
            FROM PREFS PDUPS
            WHERE PDUPS.SCHOOLID  = EV.SCHOOLID
            AND LOWER(PDUPS.NAME) = 'att_calccntattothschenrthissch'
            AND PDUPS.YEARID      = EV.YEARID
            ) )                   = '1'
        THEN NVL(
          (SELECT SUM(
            CASE
              WHEN NVL(ATTT.ENTRYCOUNT, 0) = 0
              THEN NVL( (
                CASE
                  WHEN AC.PRESENCE_STATUS_CD = 'Absent'
                  AND AC.CALCULATE_ADA_YN    = 1
                  THEN BSI.MINUTES_ATTENDED
                  WHEN AC.PRESENCE_STATUS_CD = 'Absent'
                  AND AC.CALCULATE_ADA_YN    = 0
                  THEN 0
                  ELSE BSI.MINUTES_ATTENDED - ATT.TOTAL_MINUTES
                END), 0)
              ELSE NVL(BSI.MINUTES_ATTENDED - ATT.TOTAL_MINUTES, 0)
            END)
          FROM ATTENDANCE ATT
          JOIN ATTENDANCE_CODE AC
          ON ATT.ATTENDANCE_CODEID = AC.ID
          JOIN CC CC
          ON ATT.CCID = CC.ID
          JOIN SECTIONS SEC
          ON ABS(CC.SECTIONID) = SEC.ID
          JOIN BELL_SCHEDULE_ITEMS BSI
          ON ATT.PERIODID = BSI.PERIOD_ID
          JOIN CALENDAR_DAY CDSUB
          ON BSI.BELL_SCHEDULE_ID = CDSUB.BELL_SCHEDULE_ID
          LEFT JOIN
            (SELECT ATTT2.ATTENDANCEID,
              COUNT(ATTT2.ATTENDANCEID) ENTRYCOUNT
            FROM ATTENDANCE_TIME ATTT2
            GROUP BY ATTT2.ATTENDANCEID
            ) ATTT
          ON ATT.ID             = ATTT.ATTENDANCEID
          WHERE ATT.STUDENTID   = CC.STUDENTID
          AND CDSUB.DATE_VALUE  = CD.DATE_VALUE
          AND ( (CDSUB.SCHOOLID = EV.SCHOOLID
          AND BSI.ADA_CODE      = 1)
          OR (CDSUB.SCHOOLID   <> EV.SCHOOLID) )
          AND CC.DATEENROLLED  <= ATT.ATT_DATE
          AND ATT.ATT_DATE      < CC.DATELEFT
          AND ATT.ATT_MODE_CODE = 'ATT_ModeMeeting'
          AND SEC.EXCLUDE_ADA   = 0
          AND ATT.STUDENTID     = EV.STUDENTID
          AND ATT.ATT_DATE      = CD.DATE_VALUE
          AND CC.DCID NOT      IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          ) ,0)
        ELSE NVL(
          (SELECT SUM(
            CASE
              WHEN NVL(ATTT.ENTRYCOUNT, 0) = 0
              THEN NVL( (
                CASE
                  WHEN AC.PRESENCE_STATUS_CD = 'Absent'
                  AND AC.CALCULATE_ADA_YN    = 1
                  THEN BSI.MINUTES_ATTENDED
                  WHEN AC.PRESENCE_STATUS_CD = 'Absent'
                  AND AC.CALCULATE_ADA_YN    = 0
                  THEN 0
                  ELSE BSI.MINUTES_ATTENDED - ATT.TOTAL_MINUTES
                END), 0)
              ELSE NVL(BSI.MINUTES_ATTENDED - ATT.TOTAL_MINUTES, 0)
            END)
          FROM ATTENDANCE ATT
          JOIN ATTENDANCE_CODE AC
          ON ATT.ATTENDANCE_CODEID = AC.ID
          JOIN CC CC
          ON ATT.CCID = CC.ID
          JOIN BELL_SCHEDULE_ITEMS BSI
          ON BSI.PERIOD_ID = ATT.PERIODID
          JOIN SECTIONS SEC
          ON ABS(CC.SECTIONID) = SEC.ID
          LEFT JOIN
            (SELECT ATTT2.ATTENDANCEID,
              COUNT(ATTT2.ATTENDANCEID) ENTRYCOUNT
            FROM ATTENDANCE_TIME ATTT2
            GROUP BY ATTT2.ATTENDANCEID
            ) ATTT
          ON ATT.ID               = ATTT.ATTENDANCEID
          WHERE ATT.STUDENTID     = CC.STUDENTID
          AND CD.BELL_SCHEDULE_ID = BSI.BELL_SCHEDULE_ID
          AND ATT.ATT_DATE       >= CC.DATEENROLLED
          AND ATT.ATT_DATE        < CC.DATELEFT
          AND ATT.ATT_MODE_CODE   = 'ATT_ModeMeeting'
          AND SEC.EXCLUDE_ADA     = 0
          AND BSI.ADA_CODE        = 1
          AND ATT.STUDENTID       = EV.STUDENTID
          AND ATT.ATT_DATE        = CD.DATE_VALUE
          AND CC.DCID NOT        IN
            (SELECT CCE.CCDCID
            FROM CC_EXCLUSIONS CCE
            WHERE CD.DATE_VALUE>=CCE.STARTDATE
            AND CD.DATE_VALUE  <=CCE.ENDDATE
            )
          ) ,0)
      END) AS MINUTES_ABSENT
    FROM PT_ENROLLMENT_ALL EV,
      CALENDAR_DAY CD,
      BELL_SCHEDULE BS
    WHERE EV.SCHOOLID       = CD.SCHOOLID
    AND EV.SCHOOLID         = 2053
    AND CD.BELL_SCHEDULE_ID = BS.ID
    AND CD.INSESSION        = 1
    AND CD.DATE_VALUE      >= EV.ENTRYDATE
    AND CD.DATE_VALUE       < EV.EXITDATE
    AND CD.DATE_VALUE      >= to_date('07/28/2018', 'mm/dd/yyyy')
    AND CD.DATE_VALUE      <= to_date('06/30/2019', 'mm/dd/yyyy');

当我尝试使用 With 子句(CTE 通用表表达式)进行重复查询时,性能会有所提高。但我相信性能仍有一定的提升空间。因此,对于这些列出的列,您可以看到有多个 case 语句,并且也有很少的代码块是重复的。有没有什么方法可以用 except 子句进行优化。感谢您提前的帮助。

此 SQL 脚本来自 Oracle。

sql oracle performance query-optimization
2个回答
1
投票

简化查询,性能可能会自动提高。

例如,

POTENTIAL_PERIODS_PRESENT
POTENTIAL_MINUTES_PRESENT
中的子查询几乎相同。他们从相同的表中读取数据,并使用相同的联接,只是使用不同的聚合函数。同时执行所有聚合函数。

转换:

SELECT COUNT(PER.PERIOD_NUMBER)
...
SELECT SUM(BSI.MINUTES_ATTENDED)
...

对于类似的事情:

JOIN
(
    SELECT STUDENTID, COUNT(PER.PERIOD_NUMBER), SELECT SUM(BSI.MINUTES_ATTENDED)
    ...
    GROUP BY STUDENTID
) STUDENT_DATA
    ON EV.STUDENID = STUDENT_DATA.STUDENTID

也许其他子查询可以转换,但它们与前两个子查询并不完全相同。您的查询非常庞大,而确切的细节是您必须痛苦地解决的事情。


-1
投票

使用以下内容:

select * into #mytemp
FROM PT_ENROLLMENT_ALL EV,
      CALENDAR_DAY CD,
      BELL_SCHEDULE BS
    WHERE EV.SCHOOLID       = CD.SCHOOLID
    AND EV.SCHOOLID         = 2053
    AND CD.BELL_SCHEDULE_ID = BS.ID
    AND CD.INSESSION        = 1
    AND CD.DATE_VALUE      >= EV.ENTRYDATE
    AND CD.DATE_VALUE       < EV.EXITDATE
    AND CD.DATE_VALUE      >= to_date('07/28/2018', 'mm/dd/yyyy')
    AND CD.DATE_VALUE      <= to_date('06/30/2019', 'mm/dd/yyyy');

select ...[all select cases of original query]...
from #mytemp
drop table #mytemp;

我相信这会解决性能问题。

© www.soinside.com 2019 - 2024. All rights reserved.