Můžete to udělat pomocí OR
:
WHERE (@Id > 0 AND Table1.Field = @Id)
OR (@Id = 0 AND Table1.Field IN (6,16,18))
Doporučil bych však použít (jak jste řekl) IF/ELSE
Když spojíte dvě podmínky, jako je tato, můžete si často vynutit neoptimální plány. např. ve vašem příkladu byste to mohli zjednodušit na schéma takto:
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);
Tím se jednoduše vyplní jeden ze sloupců čísly 0-2047, která se v každém opakují 4krát (jen pro některé příklady dat). Pak Pokud vytvořím dvě procedury, jednu, která používá 'IF/ELSE' jednu, která kombinuje výše uvedená kritéria:
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
Protože ke kompilaci dotazů dojde pouze jednou (pokud výslovně neřeknete jinak), optimalizátor nevybere jiný plán v závislosti na tom, zda postupu předáte 0 nebo předáte ID> 0, takže platí obojí:
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;
Dá tento plán:
Druhý postup je schopen odhadnout nejlepší plán provedení mnohem lépe, takže spusťte toto:
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;
Poskytuje následující plán:
Příklady ze skutečného světa se budou samozřejmě lišit a já jsem záměrně vytvořil příklad, který dokazuje můj názor. Je trochu větší úsilí duplikovat velké množství kódu pomocí IF/ELSE
, ale často to stojí za to.