SQL: WHERE yan tümcesi içinde IF yan tümcesi


204

MS SQL'de bir WHERE yan tümcesi içinde bir IF yan tümcesi kullanmak mümkün mü ?

Misal:

WHERE
    IF IsNumeric(@OrderNumber) = 1
        OrderNumber = @OrderNumber
    ELSE
        OrderNumber LIKE '%' + @OrderNumber + '%'

Yanıtlar:


212

Bir CASE deyimi kullanın
GÜNCELLEME: Önceki sözdizimi (birkaç kişi tarafından işaret edildiği gibi) çalışmaz. CASE'i aşağıdaki gibi kullanabilirsiniz:

WHERE OrderNumber LIKE
  CASE WHEN IsNumeric(@OrderNumber) = 1 THEN 
    @OrderNumber 
  ELSE
    '%' + @OrderNumber
  END

Veya @ NJ Reed'in işaret ettiği gibi bir IF deyimini kullanabilirsiniz .


[Yazarın GÜNCELLEMESİ'nden sonra not]: Bu işe yarar, ancak bir eşleşme bulunduğundan emin olmak için her iki tarafı da TRIM () kullanmalısınız. Eşleşmeyen nadir hala kenar vakaları var.
Euro Micelli

1
CASEÇoğu durumda kullanmak uygun çözümdür. Benim durumumda, karşılaştırma operatörünü değiştirmek istedim ve dolayısıyla bir sonraki yaklaşımı kullandım.
Birla

142

Bunu herhangi bir IF veya CASE olmadan yapabilmelisiniz

 WHERE 
   (IsNumeric(@OrderNumber) AND
      (CAST OrderNumber AS VARCHAR) = (CAST @OrderNumber AS VARCHAR)
 OR
   (NOT IsNumeric(@OrderNumber) AND
       OrderNumber LIKE ('%' + @OrderNumber))

SQL'in lezzetine bağlı olarak, sipariş numarasındaki dökümleri, örtülü dökümlerin desteklenip desteklenmemesine bağlı olarak bir INT veya VARCHAR'a ayarlamanız gerekebilir.

Bu bir WHERE yan tümcesinde çok yaygın bir tekniktir. WHERE yan tümcesine bir "IF" mantığı uygulamak istiyorsanız, tek yapmanız gereken, boolean AND ile ekstra koşulu uygulanması gereken bölüme eklemektir.


2
Yine de, tüm bu koşullar değerlendirildiğinden, CASE çözümü üzerinde bir miktar performans isabeti aldığınızı hayal ediyorum, hayır?
Kevin Fairchild

Her zaman SQL'de koşullu ifadeleri böyle bir mantıksal mantıkla değiştirebileceğini unutuyorum. Hatırlatma için teşekkürler, çok kullanışlı bir teknik!
CodexArcanum

1
Bu çözüm aslında SQL Server'ın mantıksal mantığı nasıl işlediğinden dolayı en iyisidir. İlk denetim başarısız olursa, SQL satırın işlenmesini durdurup devam edeceğinden, yan tümcelerin boole durumlarından daha az verimli olduğu CASE deyimleri. Bu işlem süresinden tasarruf etmenizi sağlar. Ayrıca, her zaman daha pahalı olan ifadeyi boole çekinizin diğer tarafına koyun.
Steve

Çok zarif bir çözüm için teşekkürler. Kullandığınız yöntem hakkında, insanlara yardımcı olabilecek bir öğretici bulundu. weblogs.sqlteam.com/jeffs/archive/2003/11/14/513.aspx
Zengin

1
@ Sağladığınız bağlantı okumak için bir kayıttır, söylediklerinizi açıklayan herkese açık bir belge var mı?
Steve

29

Bir IF deyimine ihtiyacınız yoktur.

WHERE
    (IsNumeric(@OrderNumber) = 1 AND OrderNumber = @OrderNumber)
OR (IsNumeric(@OrderNumber) = 0 AND OrderNumber LIKE '%' + @OrderNumber + '%')

2
Bu yaklaşımı gerçekten seviyorum. Alternatif kullanım: Yalnızca AdmUseId değeri where (@AdmUserId is null or CurrentOrder.CustomerAdmUserId = @AdmUserId) varsa filtreleyin : Veya yalnızca IncludeDeleted = 0 ise filtreleyin:where (@IncludeDeleted = 1 or ItemObject.DeletedFlag = 0)
Kasper Halvas Jensen

WHERE yan tümcesi içinde bir IN filtresi kullanıldığında bu iyi çalışır. COALESCE'i kullanmak zorunda olduğunuz için bunu CASE ile karıştırmak zorlaşıyor ve okumak zor, okunması kolay bir mantık. NOT IN veya IN filtresi için WHERE yan tümcesinde TSQL CASE deyimi
pholcroft

14

Bunu SQL'de yapmanın iyi bir yolu yoktur. Gördüğüm bazı yaklaşımlar:

1) Boole operatörleriyle birlikte CASE kullanın:

WHERE
    OrderNumber = CASE 
        WHEN (IsNumeric(@OrderNumber) = 1)
        THEN CONVERT(INT, @OrderNumber)
        ELSE -9999 -- Some numeric value that just cannot exist in the column
    END
    OR 
    FirstName LIKE CASE
        WHEN (IsNumeric(@OrderNumber) = 0)
        THEN '%' + @OrderNumber
        ELSE ''
    END

2) SELECT dışındaki IF'leri kullanın

IF (IsNumeric(@OrderNumber)) = 1
BEGIN
    SELECT * FROM Table
    WHERE @OrderNumber = OrderNumber
END ELSE BEGIN
    SELECT * FROM Table
    WHERE OrderNumber LIKE '%' + @OrderNumber
END

3) Uzun bir dize kullanarak, SQL ifadenizi koşullu olarak oluşturun ve EXEC kullanın

3. yaklaşım iğrençtir, ancak böyle bir dizi değişken koşulunuz varsa işe yarayan neredeyse tek düşüncedir.


dördüncü yaklaşım, tüm IF...ELSE...koşullarınızı yukarıdaki @ njr101 yanıtında olduğu gibi boole ANDve s'ye dönüştürmektir OR. ^ Bu yaklaşımın dezavantajı, çok sayıda IFvarsa veya yuvalanmış çok sayıda varsa, beyin kızartma zor olabilir
Don Cheadle


4

CASE deyimini istiyorsunuz

WHERE OrderNumber LIKE
CASE WHEN IsNumeric(@OrderNumber)=1 THEN @OrderNumber ELSE '%' + @OrderNumber END

3

Sanırım ... = / case gibi ... o zaman ... Boolean'larla çalışabilir. T-SQL kullanıyorum.

Senaryo: Diyelim ki bool yanlışsa Person-30'un hobilerini, bool doğru ise Person-42'nin hobilerini almak istiyorsunuz. (Bazılarına göre, hobi aramaları iş hesaplama döngülerinin% 90'ından fazlasını oluşturur, bu nedenle yakın ödeme yapın.).

CREATE PROCEDURE sp_Case
@bool   bit
AS
SELECT Person.Hobbies
FROM Person
WHERE Person.ID = 
    case @bool 
        when 0 
            then 30
        when 1
            then 42
    end;

2
NEREDE (IsNumeric (@OrderNumber) <> 1 VEYA OrderNumber = @OrderNumber) 
             AND (IsNumber (@OrderNumber) = 1 VEYA OrderNumber '%' GİBİ 
                                              + @OrderNumber + '%')

Konjonktif Normal Form yeniden yazma kuralı:IF P THEN Q ELSE R <=> ( ( NOT P ) OR Q ) AND ( P OR R )
gün1

1

CASE deyimi her zaman IF'den daha iyi bir seçenektir .

  WHERE  vfl.CreatedDate >= CASE WHEN @FromDate IS NULL THEN vfl.CreatedDate ELSE  @FromDate END
    AND vfl.CreatedDate<=CASE WHEN @ToDate IS NULL THEN vfl.CreatedDate ELSE @ToDate END 

1
    WHERE OrderNumber LIKE CASE WHEN IsNumeric(@OrderNumber) = 1 THEN @OrderNumber ELSE  '%' + @OrderNumber END

Bu durumda Durum düzgün çalışacaktır.


0

Aşağıdaki örnek, Boole ifadesinin bir parçası olarak bir sorgu yürütür ve ardından Boolean ifadesinin sonucuna bağlı olarak biraz farklı ifade blokları yürütür. Her ifade bloğu BEGIN ile başlar ve END ile tamamlanır.

USE AdventureWorks2012;
GO
DECLARE @AvgWeight decimal(8,2), @BikeCount int
IF 
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%' ) > 5
BEGIN
   SET @BikeCount = 
        (SELECT COUNT(*) 
         FROM Production.Product 
         WHERE Name LIKE 'Touring-3000%');
   SET @AvgWeight = 
        (SELECT AVG(Weight) 
         FROM Production.Product 
         WHERE Name LIKE 'Touring-3000%');
   PRINT 'There are ' + CAST(@BikeCount AS varchar(3)) + ' Touring-3000 bikes.'
   PRINT 'The average weight of the top 5 Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.';
END
ELSE 
BEGIN
SET @AvgWeight = 
        (SELECT AVG(Weight)
         FROM Production.Product 
         WHERE Name LIKE 'Touring-3000%' );
   PRINT 'Average weight of the Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.' ;
END ;
GO

İç içe IF ... ELSE deyimlerini kullanma Aşağıdaki örnek, bir IF… ELSE deyiminin diğerinin içine nasıl yerleştirilebileceğini gösterir. Her bir ifadeyi test etmek için @Number değişkenini 5, 50 ve 500 olarak ayarlayın.

DECLARE @Number int
SET @Number = 50
IF @Number > 100
   PRINT 'The number is large.'
ELSE 
   BEGIN
      IF @Number < 10
      PRINT 'The number is small'
   ELSE
      PRINT 'The number is medium'
   END ;
GO

2
Bu alakalı görünmüyor. WHERE deyiminde bir IF (veya herhangi bir koşullu kod) kullanmaz.
Vince Bowdren

0

Sql sunucusunda ben sadece parametre yanlış ve doğru ise bir ve deyimi kullanmak istedim aynı sorunu vardı doğru ve yanlış her iki değeri göstermek zorunda böylece bu şekilde kullanılır

(T.IsPublic = @ShowPublic or  @ShowPublic = 1)

-1
If @LstTransDt is Null
                begin
                    Set @OpenQty=0
                end
            else
                begin
                   Select   @OpenQty=IsNull(Sum(ClosingQty),0)  
                   From  ProductAndDepotWiseMonitoring  
                   Where   Pcd=@PCd And PtpCd=@PTpCd And TransDt=@LstTransDt      
                end 

Bunun yardımcı olup olmadığını görün.


-6
USE AdventureWorks2012;
GO
IF 
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%' ) > 5
PRINT 'There are more than 5 Touring-3000 bicycles.'
ELSE PRINT 'There are 5 or less Touring-3000 bicycles.' ;
GO

Bu alakalı görünmüyor. WHERE deyiminde bir IF (veya herhangi bir koşullu kod) kullanmaz.
Vince Bowdren
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.