2016-09-18 59 views
1

我試圖通過減少內部查詢來提高查詢的性能。SQL Server:提高內部查詢的性能

我將需要第一個,因爲它會返回ReasonTUM。

但是,我想使用ReasonTUM的情況下,它也返回一個數字。

我該如何做到這一點?我試過在原始查詢中引用mms.sMachineStateName,但它沒有檢測到列。

我能想到的唯一方法是使用另一個子查詢,但由於連接,這需要大約1分鐘來返回300行。

declare @ReportingStart datetime = '20160917 07:00' 
declare @ReportingEnd datetime = '20160918 07:00' 

SELECT 
     [sWorkcellDescription] 
     ,[tStart] 
     ,[dDurationSeconds]/60 as Duration_m 
     ,[sStateDescription] 
     ,datepart(hh,tstart) as myHr 
     ,case when convert(time,tstart)< '07:00' then dateadd(dd,-1,convert(date,tstart)) else convert(date,tstart) end as myDate, 
     cast(dateadd(hour,datepart(hh,tstart),0) as datetime) as dispTime, 
     (
      select top 1 mms.sMachineStateName 
      from OEEEvent oe 
      inner join RSBizWare.dbo.OEEConfigEvent ce on oe.lOEEConfigEventId = ce.lOEEConfigEventId 
      inner join RSBizWare.dbo.OEELOVCodeVal rs on oe.sStartVal = rs.sDescription and ce.lOEEIntRSSqlId=rs.lOEELOVCodeId 
      inner join RSBizWare.dbo.OEEStateConfig mms on rs.lMachineState = mms.lOEEStateConfigId 
      where qq.tStart between oe.tStart and oe.tEnd and oe.sPartId='Ore-Hoist' 
      order by qq.tStart asc 
     ) as ReasonTUM, 
       (
      select top 1 case 
     when mms.sMachineStateName = 'Production' then '1' 
     when mms.sMachineStateName = 'Unscheduled Production' then '2' 
     when mms.sMachineStateName = 'Idle time' then '3' 
     when mms.sMachineStateName = 'Opportune Maintenance' then '4' 
     when mms.sMachineStateName = 'Planned External Downtime' then '5' 
     when mms.sMachineStateName = 'Planned External Downtime' then '5' 
     when mms.sMachineStateName = 'Planned Maintenance Mechanical' then '5' 
     when mms.sMachineStateName = 'Planned Maintenance Electrical' then '6' 
     when mms.sMachineStateName = 'Unplanned Downtime Operational' then '7' 
     when mms.sMachineStateName = 'Unplanned Downtime Mechanical' then '8' 
     when mms.sMachineStateName = 'Unplanned Downtime Electrical' then '9' 
     else '99' end 
      from OEEEvent oe 
      inner join RSBizWare.dbo.OEEConfigEvent ce on oe.lOEEConfigEventId = ce.lOEEConfigEventId 
      inner join RSBizWare.dbo.OEELOVCodeVal rs on oe.sStartVal = rs.sDescription and ce.lOEEIntRSSqlId=rs.lOEELOVCodeId 
      inner join RSBizWare.dbo.OEEStateConfig mms on rs.lMachineState = mms.lOEEStateConfigId 
      where qq.tStart between oe.tStart and oe.tEnd and oe.sPartId='Ore-Hoist' 
     ) as rank 
FROM 
    [RSBizWare].[dbo].[OEEQStateData] qq 
WHERE 
    (tstart >= @ReportingStart AND tStart < @ReportingEnd) 
    AND sWorkcellDescription = 'Hoisting' 
    AND dDurationSeconds > 5 
ORDER BY 
    tStart ASC 
+0

如何內部查詢涉及外? JOIN通常只有在1)它們不能作爲一個集合被執行時(一種簡單的方式來推斷它們可以/被執行,因爲它們可以將內部查詢本身變成JOIN),或者2)它們缺少查詢的適當索引。 – user2864740

+0

閱讀執行計劃。 – qxg

回答

3

使用OUTER APPLY,以避免調用sub-query兩次

SELECT [sworkcelldescription], 
     [tstart], 
     [ddurationseconds]/60         AS Duration_m, 
     [sstatedescription], 
     Datepart(hh, tstart)          AS myHr, 
     CASE 
     WHEN CONVERT(TIME, tstart) < '07:00' THEN Dateadd(dd, -1, 
                CONVERT(DATE, tstart 
                )) 
     ELSE CONVERT(DATE, tstart) 
     END              AS myDate, 
     Cast(Dateadd(hour, Datepart(hh, tstart), 0) AS DATETIME) AS dispTime, 
     OA.reasontum, 
     OA.[rank] 
FROM [RSBizWare].[dbo].[oeeqstatedata] qq 
     OUTER apply (SELECT TOP 1 mms.smachinestatename, 
           CASE mms.smachinestatename 
            WHEN 'Production' THEN '1' 
            WHEN 'Unscheduled Production' THEN '2' 
            WHEN 'Idle time' THEN '3' 
            WHEN 'Opportune Maintenance' THEN '4' 
            WHEN 'Planned External Downtime' THEN '5' 
            WHEN 'Planned External Downtime' THEN '5' 
            WHEN 'Planned Maintenance Mechanical' THEN '5' 
            WHEN 'Planned Maintenance Electrical' THEN '6' 
            WHEN 'Unplanned Downtime Operational' THEN '7' 
            WHEN 'Unplanned Downtime Mechanical' THEN '8' 
            WHEN 'Unplanned Downtime Electrical' THEN '9' 
            ELSE '99' 
           END AS [Rank] 
        FROM oeeevent oe 
          INNER JOIN rsbizware.dbo.oeeconfigevent ce 
            ON oe.loeeconfigeventid = 
             ce.loeeconfigeventid 
          INNER JOIN rsbizware.dbo.oeelovcodeval rs 
            ON oe.sstartval = rs.sdescription 
             AND ce.loeeintrssqlid = rs.loeelovcodeid 
          INNER JOIN rsbizware.dbo.oeestateconfig mms 
            ON rs.lmachinestate = mms.loeestateconfigid 
        WHERE qq.tstart BETWEEN oe.tstart AND oe.tend 
          AND oe.spartid = 'Ore-Hoist' 
        ORDER BY qq.tstart ASC) OA 
WHERE (tstart >= @ReportingStart 
     AND tstart < @ReportingEnd) 
     AND sworkcelldescription = 'Hoisting' 
     AND ddurationseconds > 5 
ORDER BY tstart ASC 
+0

在這兩個查詢選擇記錄使用TOP 1其中1與ORDER BY和另一個沒有,但在你的方式兩個值使用ORDER BY選擇,如果兩個結果需要在相同的順序,那麼它的罰款否則是返回相同的結果? – Susang

+0

@Suraz - 如果沒有錯誤OP想在這兩個子查詢中排序 –

+0

@Prdp - 查詢性能從59s到28s!非常感謝你 – GlenCloncurry