2016-06-21 2 views
1

Ich habe eine gespeicherte Proc, wo ich die gleiche "nicht existiert" -Klausel wiederholt habe. Jede 'not exists' -Klausel in jedem select wird in den nachfolgenden select-Abfragen wiederholt und die 'exist'-Klausel wird' non exist 'in den nachfolgenden select-Abfragen. Gibt es Möglichkeit, ich kann jedes "nicht existiert" und "existiert" nur einmal und speichern Sie diese Ergebnisse und verwenden Sie sie über die proc? Was ist der optimierte Weg dafür? Vielen Dank!Wie werden repetitive exists und non exists in sql gespeicherten Prozeduren optimiert?

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[sp_GetCaseType] 
@ID numeric(18,0) 
AS 

BEGIN     
SET NOCOUNT ON;  
DECLARE @cnt int; 

SELECT @cnt = COUNT(*) 
      FROM tblCase c WITH (NOLOCK) 
      join tblDepartment cd WITH (NOLOCK) on cd.DepartmentID = c.DepartmentID 
      join tblType ct WITH (NOLOCK) on ct.TypeID = cd.TypeID 
      WHERE ct.Type in ('AG', 'PH') 
      and 
      not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
         join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
         WHERE ca.Code in ('Z', 'W') 
         and ch.ID = @ID) 
      and 
      c.ID = @ID 

IF (@cnt > 1) 
    RETURN 'CATEGORY 1' 

SELECT @cnt = COUNT(*) 
      FROM tblCase c WITH (NOLOCK) 
      join tblDepartment cd WITH (NOLOCK) on cd.DepartmentID = c.DepartmentID 
      join tblType ct WITH (NOLOCK) on ct.TypeID = cd.TypeID 
      WHERE ct.Type in ('AG', 'PH') 
      and 
      not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
         join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
         WHERE ca.Code in ('Z', 'W') 
         and ch.ID = @ID) 
      and 
      exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
        join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
        WHERE ca.Code in ('N', 'O') 
        and ch.ID = @ID) 
      and 
      c.ID = @ID 

IF (@cnt > 1) 
    RETURN 'CATEGORY 2' 

SELECT @cnt = COUNT(*) 
     FROM tblCase c WITH (NOLOCK) 
     join tblDepartment cd WITH (NOLOCK) on cd.DepartmentID = c.DepartmentID 
     join tblType ct WITH (NOLOCK) on ct.TypeID = cd.TypeID 
     WHERE ct.Type in ('AG', 'PH') 
     and 
     not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
        join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
        WHERE ca.Code in ('Z', 'W') 
        and ch.ID = @ID) 
     and 
     not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
       join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
       WHERE ca.Code in ('N', 'O') 
       and ch.ID = @ID) 
     and 
     exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
       join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
       WHERE ca.Code in ('D', 'B') 
       and ch.ID = @ID) 
     and 
     c.ID = @ID 

IF (@cnt > 1) 
    RETURN 'CATEGORY 2' 


SELECT @cnt = COUNT(*) 
     FROM tblCase c WITH (NOLOCK) 
     join tblDepartment cd WITH (NOLOCK) on cd.DepartmentID = c.DepartmentID 
     join tblType ct WITH (NOLOCK) on ct.TypeID = cd.TypeID 
     WHERE ct.Type in ('AG', 'PH') 
     and 
     not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
        join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
        WHERE ca.Code in ('Z', 'W') 
        and ch.ID = @ID) 
     and 
     not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
       join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
       WHERE ca.Code in ('N', 'O') 
       and ch.ID = @ID) 
     and 
     not exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
       join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
       WHERE ca.Code in ('D', 'B') 
       and ch.ID = @ID) 
     and 
     exists (SELECT * FROM tblCharge ch WITH (NOLOCK) 
       join tblAction ca WITH (NOLOCK) on ch.ActionID = ca.ActionID 
       WHERE ca.Code in ('A', 'C') 
       and ch.ID = @ID) 
     and 
     c.ID = @ID 

IF (@cnt > 1) 
    RETURN 'CATEGORY 2' 

END 
+0

Einfach fragen ... wenn Sie es bei den Ausführungsplan aussehen, es lassen vermuten, dass es automatisch optimiert es für Du? –

Antwort

1

versuchen, die Kombination existiert und nicht existiert in einer Abfrage und auch nur top 1 zurückgeben. Auf diese Weise minimieren Sie die Anzahl der zurückgegebenen Zeilen pro SELECT Anweisung innerhalb der WHERE Klausel. Auch hinzugefügt SET NOCOUNT ON; auf Ihre proc dies eine schnelle und einfache Art und Weise ist eine Leistungssteigerung zu gewinnen:

SET ANSI_NULLS ON; 
GO 

SET QUOTED_IDENTIFIER ON; 
GO 

ALTER PROCEDURE [dbo].[sp_GetCaseType] @ID NUMERIC(18, 0) 
AS 
    SET NOCOUNT ON; 
    BEGIN 
     SET NOCOUNT ON; 
     DECLARE @cnt INT; 
     SELECT @cnt = COUNT(*) 
     FROM tblCase c WITH (NOLOCK) 
      JOIN tblDepartment cd WITH (NOLOCK) ON cd.DepartmentID = c.DepartmentID 
      JOIN tblType ct WITH (NOLOCK) ON ct.TypeID = cd.TypeID 
     WHERE ct.Type IN('AG', 'PH') 
      AND NOT EXISTS 
         (SELECT * 
         FROM tblCharge ch WITH (NOLOCK) 
           JOIN tblAction ca WITH (NOLOCK) ON ch.ActionID = ca.ActionID 
         WHERE ca.Code IN('Z', 'W') 
           AND ch.ID = @ID) 
         AND c.ID = @ID; 
     IF(@cnt > 1) 
      RETURN 'CATEGORY 1'; 
     SELECT @cnt = COUNT(*) 
     FROM tblCase c WITH (NOLOCK) 
      JOIN tblDepartment cd WITH (NOLOCK) ON cd.DepartmentID = c.DepartmentID 
      JOIN tblType ct WITH (NOLOCK) ON ct.TypeID = cd.TypeID 
     WHERE ct.Type IN('AG', 'PH') 
      AND EXISTS 
        (SELECT TOP 1 1 
         FROM   tblCharge ch WITH (NOLOCK) 
           JOIN tblAction ca WITH (NOLOCK) ON ch.ActionID = ca.ActionID 
         WHERE  ca.Code NOT IN('Z', 'W') 
           AND ca.Code IN('N', 'O') 
           AND ch.ID = @ID) 
         AND c.ID = @ID; 
     IF(@cnt > 1) 
      RETURN 'CATEGORY 2'; 
     SELECT @cnt = COUNT(*) 
     FROM tblCase c WITH (NOLOCK) 
      JOIN tblDepartment cd WITH (NOLOCK) ON cd.DepartmentID = c.DepartmentID 
      JOIN tblType ct WITH (NOLOCK) ON ct.TypeID = cd.TypeID 
     WHERE ct.Type IN('AG', 'PH') 
      AND EXISTS 
        (SELECT TOP 1 1 
         FROM   tblCharge ch WITH (NOLOCK) 
           JOIN tblAction ca WITH (NOLOCK) ON ch.ActionID = ca.ActionID 
         WHERE  ca.Code NOT IN('Z', 'W', 'N', 'O') 
           AND ca.Code IN('D', 'B') 
           AND ch.ID = @ID) 
         AND c.ID = @ID; 
     IF(@cnt > 1) 
      RETURN 'CATEGORY 2'; 
     SELECT @cnt = COUNT(*) 
     FROM tblCase c WITH (NOLOCK) 
      JOIN tblDepartment cd WITH (NOLOCK) ON cd.DepartmentID = c.DepartmentID 
      JOIN tblType ct WITH (NOLOCK) ON ct.TypeID = cd.TypeID 
     WHERE ct.Type IN('AG', 'PH') 
      AND EXISTS 
        (SELECT TOP 1 1 
         FROM   tblCharge ch WITH (NOLOCK) 
           JOIN tblAction ca WITH (NOLOCK) ON ch.ActionID = ca.ActionID 
         WHERE  ca.Code NOT IN('Z', 'W', 'N', 'O', 'D', 'B') 
           AND ca.Code IN('A', 'C') 
           AND ch.ID = @ID) 
         AND c.ID = @ID; 
     IF(@cnt > 1) 
      RETURN 'CATEGORY 2'; 
    END; 
+1

Es besteht keine Notwendigkeit für "SELECT TOP 1" mit "EXISTS". SQL Server ist intelligent genug, um zu stoppen, wenn eine einzelne Zeile gefunden wird, die den Kriterien entspricht, und sie schließt sie automatisch kurz. –

+0

@TomH danke für Tom. Gut zu wissen. –

1

Wenn sie identisch sind und wenn sie nicht korrelierte Unterabfragen sind, dann können Sie nur die Ergebnisse in einer Variablen zu Beginn Ihrer gespeicherten Prozedur speichern und dann diese Variable in den Rest Ihrer Abfragen verwenden:

DECLARE 
    @zw_exists BIT = 0 

IF EXISTS (SELECT * FROM ... WHERE Code IN ('Z', 'W') AND CH.ID = @ID) 
    @zw_exists = 1 

Machen Sie dasselbe für jede Art von Abfrage, dann verwenden Sie einfach die Variable in Ihren anderen Abfragen.