Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Instrução Sql Case dentro do Sql IN


Você pode fazer isso usando um OR :
WHERE   (@Id > 0 AND Table1.Field = @Id)
OR      (@Id = 0 AND Table1.Field IN (6,16,18))

No entanto, eu aconselharia usar (como você disse) IF/ELSE , ao combinar duas condições como essa, muitas vezes você pode forçar planos abaixo do ideal. por exemplo, no seu exemplo, você pode simplificar isso para um esquema da seguinte maneira:
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);

Isso simplesmente preenche uma das colunas com os números 0-2047 repetidos 4 vezes cada (apenas para alguns dados de exemplo). Então, se eu criar dois procedimentos, um que usa 'IF/ELSE' um que combina os critérios acima:
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

Como a compilação de consultas acontecerá apenas uma vez (a menos que você diga explicitamente o contrário), o otimizador não escolherá um plano diferente dependendo de você passar 0 ou passar um ID> 0 para o procedimento, portanto, ambos:
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;

Vai dar este plano:



O segundo procedimento é capaz de estimar muito melhor o melhor plano de execução, então execute isso:
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;

Apresenta o seguinte plano:



Os exemplos do mundo real obviamente variam, e deliberadamente construí um exemplo que prova meu ponto de vista. É um pouco mais trabalhoso duplicar muito código usando IF/ELSE , mas muitas vezes vale a pena.