Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Sql Case-Anweisung innerhalb von Sql IN

Sie können dies mit einem OR tun :

WHERE   (@Id > 0 AND Table1.Field = @Id)
OR      (@Id = 0 AND Table1.Field IN (6,16,18))

Ich würde jedoch raten, (wie Sie gesagt haben) IF/ELSE zu verwenden , wenn Sie zwei Bedingungen wie diese zusammenmischen, können Sie oft suboptimale Pläne erzwingen. zB In Ihrem Beispiel könnten Sie dies wie folgt zu einem Schema vereinfachen:

CREATE TABLE T
(   ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
    Field INT NOT NULL, 
    SomeOtherField INT NULL
);
GO
INSERT T  (Field)
SELECT  Number
FROM    Master..spt_values
        CROSS JOIN (VALUES (1), (2), (3)) t (A)
WHERE   Type = 'P'
GO
CREATE NONCLUSTERED INDEX IX_T_Field ON T (Field) INCLUDE (SomeOtherField);

Dies füllt einfach eine der Spalten mit den Zahlen 0-2047, die jeweils 4 Mal wiederholt werden (nur für einige Beispieldaten). Wenn ich dann zwei Prozeduren erstelle, eine, die 'IF/ELSE' verwendet, eine, die die Kriterien wie oben kombiniert:

CREATE PROCEDURE dbo.Test @ID INT
AS
    SELECT  ID, Field, SomeOtherField
    FROM    T
    WHERE   (@Id > 0 AND T.Field = @Id)
    OR      (@Id = 0 AND T.Field IN (6,16,18))

GO
CREATE PROCEDURE dbo.Test2 @ID INT
AS
    IF @ID = 0
        SELECT  ID, Field, SomeOtherField
        FROM    T
        WHERE   T.Field IN (6, 16, 18)
    ELSE
        SELECT  ID, Field, SomeOtherField
        FROM    T
        WHERE   T.Field = @Id
GO

Da die Kompilierung von Abfragen nur einmal erfolgt (sofern Sie nicht ausdrücklich etwas anderes angeben), wählt der Optimierer keinen anderen Plan aus, je nachdem, ob Sie 0 oder eine ID> 0 an die Prozedur übergeben, also beides:

EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;

Gibt diesen Plan:

Das zweite Verfahren ist in der Lage, den besten Ausführungsplan viel besser abzuschätzen, also führen Sie Folgendes aus:

EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;

Gibt den folgenden Plan:

Beispiele aus der realen Welt werden natürlich variieren, und ich habe absichtlich ein Beispiel konstruiert, das meinen Standpunkt beweist. Es ist etwas aufwändiger, viel Code mit IF/ELSE zu duplizieren , aber es lohnt sich oft.