2014-08-29 128 views
0

我有一个查询SQL查询如下,任何人都可以为此提出任何优化;我认为联盟行动的大部分工作正在进行 - 是否还有其他方法可以获得相同的结果? 基本上我想查询UNION的第一部分,如果每条记录都没有结果,那么需要运行第二部分。请帮忙。 :如何优化SQL查询?

SET dateformat dmy; 

WITH incidentcategory 
    AS (
    SELECT 1 ord, i.IncidentId, rl.Description Category FROM incident i 
     JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId 
     JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId 
     JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId 
     JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId 

    UNION 

    SELECT 2 ord, i.incidentid, 
       rl.description Category 
     FROM incident i 
       JOIN incidentreportlikelihood l 
        ON i.incidentid = l.incidentid 
       JOIN incidentreportseverity s 
        ON i.incidentid = s.incidentid 
       JOIN likelihoodseverity ls 
        ON l.likelihoodid = ls.likelihoodid 
        AND s.severityid = ls.severityid 
       JOIN risklevel rl 
        ON ls.risklevelid = rl.risklevelid 

       ) , 
ic AS (
     SELECT ROW_NUMBER() OVER (PARTITION BY i.IncidentId ORDER BY (CASE WHEN incidentTime IS NULL THEN GETDATE() ELSE incidentTime END) DESC,ord ASC) rn, 
         i.incidentid, 
         dbo.Incidentdescription(i.incidentid, '', 
         '', 
         '', '') 
           IncidentDescription, 
         dbo.Dateconverttimezonecompanyid(closedtime, 
         i.companyid) 
           ClosedTime, 
         incidenttime, 
         incidentno, 
         Isnull(c.category, '') 
           Category, 
         opencorrectiveactions, 
         reportcompleted, 
         Isnull(classificationcompleted, 0) 
           ClassificationCompleted, 
         Cast ((CASE 
            WHEN closedtime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           IncidentClosed, 
         Cast ((CASE 
            WHEN investigatorfinishedtime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           InvestigationFinished, 
         Cast ((CASE 
            WHEN investigationcompletetime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           InvestigationComplete, 
         Cast ((CASE 
            WHEN investigatorassignedtime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           InvestigatorAssigned, 
         Cast ((CASE 
            WHEN (SELECT Count(*) 
             FROM incidentinvestigator 
             WHERE incidentid = i.incidentid 
               AND personid = 1588 
               AND tablename = 'AdminLevels') = 0 
           THEN 0 
            ELSE 1 
           END) AS BIT) 
           IncidentInvestigator, 
         (SELECT dbo.Strconcat(osname) 
         FROM (SELECT TOP 10 osname 
           FROM incidentlocation l 
             JOIN organisationstructure o 
              ON l.locationid = o.osid 
           WHERE incidentid = i.incidentid 
           ORDER BY l.locorder) loc) 
           Location, 
         Isnull((SELECT TOP 1 teamleader 
           FROM incidentinvestigator 
           WHERE personid = 1588 
             AND tablename = 'AdminLevels' 
             AND incidentid = i.incidentid), 0) 
           TeamLeader, 
         incidentstatus, 
         incidentstatussearch 
     FROM incident i 
       LEFT OUTER JOIN incidentcategory c 
          ON i.incidentid = c.incidentid 
     WHERE i.isdeleted = 0 
       AND i.companyid = 158 
       AND incidentno <> 0 
       --AND reportcompleted = 1 
       --AND investigatorassignedtime IS NOT NULL 
       --AND investigatorfinishedtime IS NULL 
       --AND closedtime IS NULL 
      ), 
ic2 AS ( 
SELECT * FROM ic WHERE rn=1 
) 
SELECT * FROM ic2 

--WHERE rownumber >= 0 
--  AND rownumber < 0 + 10 
--WHERE ic2.incidentid in(53327,53538) 
--WHERE ic2.incidentid = 53338 

ORDER BY incidentid DESC 

以下是执行计划我: https://www.dropbox.com/s/50dcpelr1ag4blp/Execution_Plan.sqlplan?dl=0

+4

你**觉得**大部分努力都在联盟中,但你可以肯定地发现,如果你告诉SSMS向你展示[执行计划](http://technet.microsoft.com/en-我们/库/ ms178071%28V = SQL.105%29.aspx)。没有更多信息,这类问题通常无法回答。模式,索引和/或理想的[sqlfiddle](http://sqlfiddle.com)显示问题将帮助我们帮助您。 – Dan 2014-08-29 05:15:55

+2

这是一个查询的问题。 – radpin 2014-08-29 05:18:12

+0

理想情况下,你应该做一个简单的例子,就像你的情况,并把它放在这里,而不是给我们整个查询。 – 2014-08-29 05:23:17

回答

2

有几个问题:

1)使用UNION ALL而不是UNION ALL,以避免额外的操作来汇总数据。 2)尝试修改众多函数调用(例如dbo.Incidentdescription())作为一个内置表值函数,以便您可以使用CROSS APPLY或OUTER APPLY来引用它。尤其是,如果这些函数再次引用一个表。

3)再次使用CROSS APPLY或OUTER APPLY将子查询从查询​​的SELECT部分​​移动到FROM部分。

4)完成上述操作后,再次检查执行计划是否有缺失的索引。此外,使用STATISTICS TIME,IO运行查询以验证表 被引用的次数是否正确(有时执行计划会使您的方向错误,尤其是涉及函数调用的情况下)...

+0

尝试了UNION ALL而不是UNION,并用OUTER APPLY替换了LEFT OUTER JOIN - 似乎花费了相同的时间。 – marifrahman 2014-08-29 07:37:24

+0

你可以请建议修改查询如何将select从select移动到from? – marifrahman 2014-08-29 07:39:55

+0

请提供重写查询的执行计划。 – Lmu92 2014-08-29 15:26:36

0

由于第一个内部查询生成的ord = 1的行,第二个生成的ord = 2的行,您应该使用UNION ALL而不是UNION。 UNION会过滤掉相同的行,并且由于您永远不会获得相同的行,因此使用UNION ALL会更高效。

此外,重写您的查询不使用WITH构造。我遇到过非常糟糕的经历。只需使用常规派生表。在查询仍然异常缓慢的情况下,尝试将某些派生表序列化为临时表,并改为查询临时表。

+0

你可以分享一个cte(“WITH构造”)比派生表执行效率更低的例子吗? – Lmu92 2014-08-29 15:25:48

+0

@ Lmu92这里没有足够的空间来提供示例。我遇到的问题通常是CTE,它们很复杂,导致很多行。在某些情况下 - 至少对于性能不佳的SQL05和SQL08 - 优化器失败并重新生成CTE(或视图)多次。建议将此CTE(或视图)“物化”为临时表,然后改为查询临时表。其他技巧(SELECT TOP 2147483647 ...)存在,但我不是一个粉丝。在Web上查找“sql server materialized cte”以获取更多上下文。 – 2014-08-30 09:13:26

0

通过从SELECT除去

(SELECT dbo.Strconcat(osname) 
         FROM (SELECT TOP 10 osname 
           FROM incidentlocation l 
             JOIN organisationstructure o 
              ON l.locationid = o.osid 
           WHERE incidentid = i.incidentid 
           ORDER BY l.locorder) loc) 
           Location, 
         Isnull((SELECT TOP 1 teamleader 
           FROM incidentinvestigator 
           WHERE personid = 1588 
             AND tablename = 'AdminLevels' 
             AND incidentid = i.incidentid), 0) 
           TeamLeader 

尝试另一种方法。避免在select中使用复杂的函数/子查询。