आप इसे OR
. का उपयोग करके कर सकते हैं :
WHERE (@Id > 0 AND Table1.Field = @Id)
OR (@Id = 0 AND Table1.Field IN (6,16,18))
हालांकि, मैं IF/ELSE
. का उपयोग करने की सलाह दूंगा (जैसा कि आपने कहा है) , इस तरह से दो स्थितियों को एक साथ मिलाते समय आप अक्सर उप-इष्टतम योजनाओं को बाध्य कर सकते हैं। उदाहरण के लिए अपने उदाहरण में आप इसे एक स्कीमा के रूप में सरल बना सकते हैं:
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);
यह केवल 0-2047 की संख्या वाले कॉलम में से एक को 4 बार दोहराता है (केवल कुछ उदाहरण डेटा के लिए)। फिर अगर मैं दो प्रक्रियाएं बनाता हूं, एक जो 'आईएफ/ईएलएसई' का उपयोग करती है जो उपरोक्त मानदंडों को जोड़ती है:
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
चूंकि प्रश्नों का संकलन केवल एक बार होगा (जब तक कि आप स्पष्ट रूप से अन्यथा न कहें), ऑप्टिमाइज़र इस आधार पर एक अलग योजना नहीं चुनेगा कि आप 0 पास करते हैं या प्रक्रिया में आईडी> 0 पास करते हैं, इसलिए निम्नलिखित दोनों:
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;
देंगे यह प्लान:
दूसरी प्रक्रिया सर्वोत्तम निष्पादन योजना का बेहतर अनुमान लगाने में सक्षम है इसलिए इसे चलाना:
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;
निम्नलिखित योजना देता है:
वास्तविक दुनिया के उदाहरण स्पष्ट रूप से भिन्न होंगे, और मैंने जानबूझकर एक उदाहरण बनाया है जो मेरी बात को साबित करता है। IF/ELSE
. का उपयोग करके बहुत सारे कोड को डुप्लिकेट करने के लिए यह थोड़ा अधिक प्रयास है , लेकिन यह अक्सर इसके लायक होता है।