sql >> Database >  >> RDS >> Sqlserver

Sql Case-instructie binnen Sql IN

Je kunt het doen met een OR :

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

Ik zou echter adviseren om (zoals je hebt gezegd) IF/ELSE . te gebruiken , als je twee voorwaarden zoals deze combineert, kun je vaak suboptimale plannen forceren. In uw voorbeeld kunt u dit bijvoorbeeld als volgt vereenvoudigen tot een schema:

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);

Dit vult eenvoudig een van de kolommen met de nummers 0-2047 die elk 4 keer worden herhaald (alleen voor enkele voorbeeldgegevens). Dan Als ik twee procedures maak, een die 'IF/ELSE' gebruikt en een die de bovenstaande criteria combineert:

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

Aangezien het compileren van query's slechts één keer plaatsvindt (tenzij u expliciet anders zegt), zal de optimizer geen ander plan kiezen, afhankelijk van of u 0 doorgeeft of een ID> 0 doorgeeft aan de procedure, dus beide:

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

Zal dit plan geven:

De tweede procedure kan het beste uitvoeringsplan veel beter inschatten, dus voer dit uit:

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

Geeft het volgende plan:

Voorbeelden uit de echte wereld zullen uiteraard variëren, en ik heb bewust een voorbeeld gemaakt dat mijn punt bewijst. Het kost iets meer moeite om veel code te dupliceren met IF/ELSE , maar het is vaak de moeite waard.



  1. MySQL krijgt rijen maar geeft de voorkeur aan de ene kolomwaarde boven de andere

  2. Oracle APEX - Opzoektabel met verschillende links

  3. mysql telt rij niet twee keer als kolomgegevens worden gedupliceerd

  4. Dubbele kolomnaam op JOIN in mysql