Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Instruction Sql Case dans Sql IN

Vous pouvez le faire en utilisant un OR :

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

Cependant, je conseillerais d'utiliser (comme vous l'avez dit) IF/ELSE , lorsque vous mélangez deux conditions comme celle-ci, vous pouvez souvent forcer des plans sous-optimaux. Par exemple, dans votre exemple, vous pouvez simplifier cela en un schéma comme suit :

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

Cela remplit simplement l'une des colonnes avec les nombres 0-2047 répétés 4 fois chacun (juste pour quelques exemples de données). Alors si je crée deux procédures, une qui utilise 'IF/ELSE' une qui combine les critères comme ci-dessus :

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

Étant donné que la compilation des requêtes n'aura lieu qu'une seule fois (sauf si vous indiquez explicitement le contraire), l'optimiseur ne choisira pas un plan différent selon que vous transmettez 0 ou transmettez un ID> 0 à la procédure, donc les deux éléments suivants :

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

Donnera ce plan :

La deuxième procédure est capable d'estimer beaucoup mieux le meilleur plan d'exécution, donc exécutez ceci :

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

Donne le plan suivant :

Les exemples du monde réel varieront évidemment, et j'ai délibérément construit un exemple qui prouve mon point de vue. Il est légèrement plus difficile de dupliquer beaucoup de code en utilisant IF/ELSE , mais cela en vaut souvent la peine.