Nasıl bir SQL SELECT IF… THEN gerçekleştiririm?


1508

IF...THENBir SQL SELECTifadede nasıl gerçekleştiririm ?

Örneğin:

SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product

14
Bu bağlantıya bir göz atmak isteyebilirsiniz . SQL WHERE yan tümceleri: CASE'den kaçının, Boolean mantığı kullanın
Birisi

3
@Birisi: gerçekten alakalı değil çünkü makale mantıklı yeniden yazma kurallarını bir çıkmazı disfonksiyona dönüştürmek için kullanmaktan bahsediyor. İpucu, 'mantıksal' kelimesidir, yani doğru veya yanlış olarak çözülen, projeksiyon için geçerli olmayan bir şeydir. TL; DR makalenin geçerli olduğu WHEREve CHECKancak SELECT.
gün

6
@ MartinSmith'in yanıtı, SQL 2012 ve sonraki sürümlerinde en zarif IIF kullanımıdır.
Murray Foxcroft

Yanıtlar:


1760

CASEİfadesi SQL IF en yakın olan ve SQL Server'ın tüm sürümlerinde desteklenir.

SELECT CAST(
             CASE
                  WHEN Obsolete = 'N' or InStock = 'Y'
                     THEN 1
                  ELSE 0
             END AS bit) as Saleable, *
FROM Product

Yalnızca CASTsonucu Boole değeri olarak istiyorsanız yapmalısınız . Birinden memnunsanız int, bu işe yarar:

SELECT CASE
            WHEN Obsolete = 'N' or InStock = 'Y'
               THEN 1
               ELSE 0
       END as Saleable, *
FROM Product

CASEifadeler diğer CASEifadelere gömülebilir ve hatta kümelere dahil edilebilir.

SQL Server Denali (SQL Server 2012) , erişimde de bulunan ( Martin Smith tarafından işaret edilen ) IIF ifadesini ekler :

SELECT IIF(Obsolete = 'N' or InStock = 'Y', 1, 0) as Saleable, * FROM Product

57
Sadece ek bir dikkat kelimesi durumunuzu kullanırken koşullarınızı parantez içine almaz. Bunu anlamak için biraz zaman aldı :)
Archan Mishra

17
ve SONU unutmayın
Simon_Weaver

8
ve AS biraz!
Cas Bloem

8
Case, When, Else ve End paralel (aynı satır boyunca) girintili olmalıdır - ve ancak o zaman daha ileriye doğru girintili olmalıdır - benim için en iyi sonucu verir.
Ujjwal Singh

6
@ReeveStrife Yalnızca SQL Server 2012+ ise
stuartdotnet

327

Vaka bildirimi bu durumda arkadaşınızdır ve iki formdan birini alır:

Basit durum:

SELECT CASE <variable> WHEN <value>      THEN <returnvalue>
                       WHEN <othervalue> THEN <returnthis>
                                         ELSE <returndefaultcase>
       END AS <newcolumnname>
FROM <table>

Genişletilmiş dava:

SELECT CASE WHEN <test>      THEN <returnvalue>
            WHEN <othertest> THEN <returnthis>
                             ELSE <returndefaultcase>
       END AS <newcolumnname>
FROM <table>

Vaka ifadelerini gerçekten süslü sipariş için maddeye göre bir sıraya koyabilirsiniz.


32
Bunun eski olduğunu biliyorum, ama sonuçta ortaya çıkan sütunu adlandırmak için bir AS Col_Namesonrası ekleyebileceğiniz belirtilmelidirEND
Ben

9
Ben her zaman ikinci olan daha basit gibi hissediyorum.
Hogan

4
Kabul ediyorum, neredeyse her zaman genişletilmiş vaka ifadesini kullanıyorum çünkü test etmek istediğim koşullar her zaman tek bir değişkenin kendisinden daha karmaşık. Ayrıca okumam daha kolay geliyor.
magnum_pi

1
Değişken olsun ya da olmasın her iki durumun da iyi açıklaması. Değişken ile koşulun, case ifadesinden sonra değişken ile koşulunuzu dayandırdığınız değişken arasındaki bir eşitliği karşılaması gerekir, değişken olmadan test etmek için kendi kendine yeterli bir koşul ekleyebilirsiniz.
Remus.A

İkinci seçenekle daha rahatım. İkisi de eşit derecede iyi.
Stanley Okpala Nwosa

277

SQL Server 2012'den bunun için IIFişlevi kullanabilirsiniz .

SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
FROM   Product

Bu etkili bir şekilde sadece steno (standart SQL olmasa da) bir yazma şeklidir CASE.

Genişletilmiş CASEversiyonla karşılaştırıldığında özlü olmayı tercih ederim .

Her ikisi de IIF()ve CASEbir SQL deyimi içinde ifadeler olarak çözümlenir ve yalnızca iyi tanımlanmış yerlerde kullanılabilir.

CASE ifadesi, Transact-SQL deyimlerinin, deyim bloklarının, kullanıcı tanımlı işlevlerin ve saklı yordamların yürütme akışını denetlemek için kullanılamaz.

İhtiyaçlarınız bu sınırlamalardan (örneğin, bazı koşullara bağlı olarak farklı şekilli sonuç kümelerini döndürme ihtiyacı) karşılanamıyorsa, SQL Server'ın yordamsal bir IFanahtar sözcüğü de vardır.

IF @IncludeExtendedInformation = 1
  BEGIN
      SELECT A,B,C,X,Y,Z
      FROM   T
  END
ELSE
  BEGIN
      SELECT A,B,C
      FROM   T
  END

Bununla birlikte, bazen bu yaklaşımla parametre koklama sorunlarından kaçınmaya dikkat edilmelidir .


6
SQL'de bir IF .. then deyimi istiyorsanız bu cevap olmalıdır.
Mr.J

91

SQL CASE'in İfadelerinin Gücü'nde bazı güzel örnekler bulabilirsiniz ve kullanabileceğiniz ifadenin ( 4guysfromrolla'dan ) böyle bir şey olacağını düşünüyorum :

SELECT
    FirstName, LastName,
    Salary, DOB,
    CASE Gender
        WHEN 'M' THEN 'Male'
        WHEN 'F' THEN 'Female'
    END
FROM Employees

4
ilginç bir tartışma için bkz. meta.stackexchange.com/questions/103053/… . Sağladığınız iki bağlantı, desteklediğim ekstra bağlam ekliyorum.
Sam Saffron

2
Ek ayrıntılarda referans gerçekten yararlıdır ve şiddetle tavsiye edilir
baymax

75

CASE kullanın. Böyle bir şey.

SELECT Salable =
        CASE Obsolete
        WHEN 'N' THEN 1
        ELSE 0
    END

50
SELECT  
(CASE 
     WHEN (Obsolete = 'N' OR InStock = 'Y') THEN 'YES'
                                            ELSE 'NO' 
 END) as Salable
, * 
FROM Product

48

Microsoft SQL Server (T-SQL)

A'da selectşunları kullanın:

select case when Obsolete = 'N' or InStock = 'Y' then 'YES' else 'NO' end

Bir wherecümlede şunu kullanın:

where 1 = case when Obsolete = 'N' or InStock = 'Y' then 1 else 0 end

1
neden where Obsolete = 'N' or InStock = 'Y'pratikte nerede yarı yarıya kesip yapmıyorsun
maksymiuk

46

Gönderen bu bağlantıyı , biz anlayabiliriz IF THEN ELSET-SQL:

IF EXISTS(SELECT *
          FROM   Northwind.dbo.Customers
          WHERE  CustomerId = 'ALFKI')
  PRINT 'Need to update Customer Record ALFKI'
ELSE
  PRINT 'Need to add Customer Record ALFKI'

IF EXISTS(SELECT *
          FROM   Northwind.dbo.Customers
          WHERE  CustomerId = 'LARSE')
  PRINT 'Need to update Customer Record LARSE'
ELSE
  PRINT 'Need to add Customer Record LARSE' 

Bu T-SQL için yeterince iyi değil mi?


3
İstekte bulunanın istediği bu değildir, ancak select deyiminin dışındaki ifadeleri kullanabileceğinizi bilmek çok yararlıdır .
Jonathan

2
EXISTS iyidir çünkü öğe bulunursa arama döngüsünün dışına çıkar. Bir COUNT, tablo satırlarının sonuna kadar çalışır. Soru ile ilgisi yok, ama bilinmesi gereken bir şey.
JustJohn

45
 SELECT
   CASE 
      WHEN OBSOLETE = 'N' or InStock = 'Y' THEN 'TRUE' 
      ELSE 'FALSE' 
   END AS Salable,
   * 
FROM PRODUCT

32

SQL Server'da basit if-else deyimi:

DECLARE @val INT;
SET @val = 15;

IF @val < 25
PRINT 'Hi Ravi Anand';
ELSE
PRINT 'By Ravi Anand.';

GO

SQL Server'da iç içe If ... else deyimi -

DECLARE @val INT;
SET @val = 15;

IF @val < 25
PRINT 'Hi Ravi Anand.';
ELSE
BEGIN
IF @val < 50
  PRINT 'what''s up?';
ELSE
  PRINT 'Bye Ravi Anand.';
END;

GO

2
Geç ama SELECTOP'nin istediği gibi içeride kullanılabilir mi?
abdul qayyum

25

SQL Server 2012'de yeni bir özellik olan IIF (yalnızca kullanabileceğimiz) eklendi:

SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product

1
Bu cevap birkaç yıl önce Martin Smith tarafından verilen cevapta daha az ayrıntıyla tekrarlanır .
jk7

1
@ jk7 bu soruya ilk cevaptı.
sandeep rawat

3
Gördüğümden değil. Cevabınız 26 Nisan 1616, Martin ise 20 Temmuz 11 gönderildi.
jk7

24

Bir CASE deyimi kullanın:

SELECT CASE
       WHEN (Obsolete = 'N' OR InStock = 'Y')
       THEN 'Y'
       ELSE 'N'
END as Available

etc...

23

Saf bit mantığı kullanın:

DECLARE @Product TABLE (
    id INT PRIMARY KEY IDENTITY NOT NULL
   ,Obsolote CHAR(1)
   ,Instock CHAR(1)
)

INSERT INTO @Product ([Obsolote], [Instock])
    VALUES ('N', 'N'), ('N', 'Y'), ('Y', 'Y'), ('Y', 'N')

;
WITH cte
AS
(
    SELECT
        'CheckIfInstock' = CAST(ISNULL(NULLIF(ISNULL(NULLIF(p.[Instock], 'Y'), 1), 'N'), 0) AS BIT)
       ,'CheckIfObsolote' = CAST(ISNULL(NULLIF(ISNULL(NULLIF(p.[Obsolote], 'N'), 0), 'Y'), 1) AS BIT)
       ,*
    FROM
        @Product AS p
)
SELECT
    'Salable' = c.[CheckIfInstock] & ~c.[CheckIfObsolote]
   ,*
FROM
    [cte] c

Çalışma demosunacase bakın : SQL Server'da yoksa .

Başlangıç için, seçilen koşulların trueve değerlerinin değerini falsehesaplamanız gerekir. İki NULLIF geliyor :

for true: ISNULL(NULLIF(p.[Instock], 'Y'), 1)
for false: ISNULL(NULLIF(p.[Instock], 'N'), 0)

bir araya geldiğinde 1 veya 0 verir. Bir sonraki kullanım bitsel operatörler .

Bu en çok WYSIWYG yöntemidir.


19
Kod Gizleme için -1. Cidden, bu yaklaşık WYSIWYG kadar alabilirsiniz! Kaba okunamayan bir karmaşa ve eğer kod üzerinde çalışmak zorunda olsaydım, gün boyu küfür olurdum ... üzgünüm: - /
Heliac

2
@Heliac View'a cte kısmını koydu ve asla karışıklığı görmeyeceksin. Uzun ve karmaşık VE, VEYA, DEĞİLDİR CASE'den daha okunaklı DEĞİLDİR (tabii ki kte dışındaki bölüm).
Tomasito

1
Bir kez koyduktan sonra, düzgünlük için bir +1 verdim, ancak sorunun şu anda yanlış olduğunu unutmayın. Bir '|' değil '&'.
Mark Hurd

3
@Heliac ile tamamen aynı fikirde. Sözdizimsel olarak doğru ve iyi çalışıyor olsa da, kolayca desteklenemez. Bir CTE'ye koymak, okunamayan bu kod parçasını başka bir yere taşıyacaktır.
objectNotFound

1
Kombinasyonu kontrol etmek için kullanılan tablo yönteminin avantajları olabilir. Bir tablo değişkeni kullanmak ve var olan sorguyla birleştirmek, büyük / küçük harf olmadan kümeye dayalı bir çözüm sağlayabilir. Bu cevap kötü bir örnektir, ancak tablo fikrinin kendisinin değeri vardır.
Suncat2000

19
SELECT 1 AS Saleable, *
  FROM @Product
 WHERE ( Obsolete = 'N' OR InStock = 'Y' )
UNION
SELECT 0 AS Saleable, *
  FROM @Product
 WHERE NOT ( Obsolete = 'N' OR InStock = 'Y' )


14
case statement some what similar to if in SQL server

SELECT CASE 
            WHEN Obsolete = 'N' or InStock = 'Y' 
               THEN 1 
               ELSE 0 
       END as Saleable, * 
FROM Product

2
Sorunun bu soruyu nasıl cevapladığı hakkında biraz açıklama yapabilir misiniz?
Guanxi

@Guanxi: Cevabım olmasa da, bir 'vaka' bir 'if-then-else' (2 vakadan birçok kişiye)
genelleştiriyor

Detaylandırabilir misin?
Peter Mortensen

13

Bu bir cevap değil, sadece çalıştığım yerde kullanılan bir CASE ifadesi örneği. İç içe bir CASE deyimi vardır. Şimdi gözlerimin neden çapraz olduğunu biliyorsun.

 CASE orweb2.dbo.Inventory.RegulatingAgencyName
    WHEN 'Region 1'
        THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
    WHEN 'Region 2'
        THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
    WHEN 'Region 3'
        THEN orweb2.dbo.CountyStateAgContactInfo.ContactState
    WHEN 'DEPT OF AGRICULTURE'
        THEN orweb2.dbo.CountyStateAgContactInfo.ContactAg
    ELSE (
            CASE orweb2.dbo.CountyStateAgContactInfo.IsContract
                WHEN 1
                    THEN orweb2.dbo.CountyStateAgContactInfo.ContactCounty
                ELSE orweb2.dbo.CountyStateAgContactInfo.ContactState
                END
            )
    END AS [County Contact Name]

1
Case ifadelerini yeniden biçimlendiren düzenleme, gayet iyi ve züppe ve daha anlaşılır kılıyor, ancak SQL yine de onu kullanan görünümde toplanıyor.
JustJohn

1
Sadece neden CASEcevaplanıp yanıt olarak işaretlenmiş olarak cevaplanacağını geziyorum, IFbunun gibi, bu hala bir CASEifade değil, bir ifadedir IF.
Mr.J

@ Mr.J: Cevabım olmasa da, bir 'dava' bir 'if-then-else' (2 vakadan birçok kişiye)
genelleştiriyor

12

Sonuçları bir tablodan diğerine aktarmak yerine sonuçları bir tabloya ilk kez ekliyorsanız, bu Oracle 11.2g'de çalışır:

INSERT INTO customers (last_name, first_name, city)
    SELECT 'Doe', 'John', 'Chicago' FROM dual
    WHERE NOT EXISTS 
        (SELECT '1' from customers 
            where last_name = 'Doe' 
            and first_name = 'John'
            and city = 'Chicago');

4
etiketler SQL Server, TSQL diyor
Malachi

11

İfadeye alternatif bir çözüm olarak, CASEtablo odaklı bir yaklaşım kullanılabilir:

DECLARE @Product TABLE (ID INT, Obsolete VARCHAR(10), InStock VARCHAR(10))
INSERT INTO @Product VALUES
(1,'N','Y'),
(2,'A','B'),
(3,'N','B'),
(4,'A','Y')

SELECT P.* , ISNULL(Stmt.Saleable,0) Saleable
FROM
    @Product P
    LEFT JOIN
        ( VALUES
            ( 'N', 'Y', 1 )
        ) Stmt (Obsolete, InStock, Saleable)
        ON  P.InStock = Stmt.InStock OR P.Obsolete = Stmt.Obsolete

Sonuç:

ID          Obsolete   InStock    Saleable
----------- ---------- ---------- -----------
1           N          Y          1
2           A          B          0
3           N          B          1
4           A          Y          1

Satılabilir durum sorguda nerede kullanılır?
Bhavin Thummar

Bu durumda kullanılabilir.
Serkan Arslan

9
SELECT CASE WHEN Obsolete = 'N' or InStock = 'Y' THEN 1 ELSE 0 
             END AS Saleable, * 
FROM Product

6

SQL Server 2012 kullananlar için IIF, Eklenen ve Case ifadelerine alternatif olarak çalışan bir özelliktir.

SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
FROM   Product 

1
Bu cevap birkaç yıl önce Martin Smith tarafından verilen cevapta daha az ayrıntıyla tekrarlanır .
jk7

6
  SELECT IIF(Obsolete = 'N' OR InStock = 'Y',1,0) AS Saleable, * FROM Product

7
Merhaba Surjeet Singh Bisht; kodunuz doğru olabilir, ancak bazı bağlamlarda daha iyi bir yanıt verir; örneğin, önerilen bu değişikliğin, belki de ilgili belgelere bir bağlantı da dahil olmak üzere, sorgunun sorununu nasıl ve neden çözeceğini açıklayabilirsiniz. Bu, onlar için daha yararlı ve aynı sorunlara çözüm arayan diğer site okuyucuları için daha yararlı olacaktır.
Vince Bowdren

5
Bu cevap yeni bir şey eklemiyor. Aslında bu aynı çizgi, 5 yılı aşkın süredir kabul edilen cevabın bir parçası olmuştur .
SL Barth - Monica'yı

1
Buna ek olarak söz etmek önemlidir IIF 2012 ile başlayan sadece SQL Server için geçerlidir
Ivan RASCON

5

Bunun gerçekte uygulanması için iki seçeneğiniz olabilir:

  1. SQL Server 2012'den tanıtılan IIF'yi kullanarak:

    SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
  2. Kullanma Select Case:

    SELECT CASE
        WHEN Obsolete = 'N' or InStock = 'Y'
            THEN 1
            ELSE 0
        END as Saleable, *
        FROM Product

4

Soru:

SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product

ANSI:

Select 
  case when p.Obsolete = 'N' 
  or p.InStock = 'Y' then 1 else 0 end as Saleable, 
  p.* 
FROM 
  Product p;

Takma ad kullanmak - pbu durumda - sorunların önlenmesine yardımcı olacaktır.


3

SQL CASE kullanmak normal If / Else ifadeleri gibidir. Aşağıdaki sorguda, eski değer = 'N' veya InStock değeri = 'Y' ise Çıkış 1 olacaktır.

SELECT
      CASE 
        WHEN obsolete = 'N' OR InStock = 'Y' 
        THEN 1 
        ELSE 0 
      END AS Salable
      , * 
FROM PRODUCT

1
Kulağa iyi geliyor. Belki açıklamak için bir iki kelime?
JQSOFT

Tıpkı normal If / Else ifadeleri gibidir. Eski değer = 'N' veya InStock değeri = 'Y' ise Çıkış 1 olacaktır. Aksi takdirde çıkış 0 olacaktır.
Tharuka

1
Teşekkür ederim. Lütfen düzenleme bu açıklamayı eklemek için yayınınızı. Like: Aşağıdaki gibi If..Then...Else..ifadeler kullanımı SQL....
JQSOFT

2
SELECT 
  CAST(
    CASE WHEN Obsolete = 'N' 
    or InStock = 'Y' THEN ELSE 0 END AS bit
  ) as Saleable, * 
FROM 
  Product

8
Şu kaynaktan: Welcome to Stack Overflow! Lütfen sadece kaynak koduyla cevap vermeyin. Çözümünüzün nasıl çalıştığı hakkında güzel bir açıklama sağlamaya çalışın. Bakınız: İyi bir cevabı nasıl yazarım? . Thanks
sɐunıɔ ןɐ qɐp

3
Bence bu çalışmadığını göreceksiniz, çünkü 'THEN' anahtar kelimesinin ardından herhangi bir çıktı eksik.
Dodecaphone

Detaylandırabilir misin?
Peter Mortensen

2

Böyle bir şey olacak:

SELECT OrderID, Quantity,
CASE
    WHEN Quantity > 30 THEN "The quantity is greater than 30"
    WHEN Quantity = 30 THEN "The quantity is 30"
    ELSE "The quantity is under 30"
END AS QuantityText
FROM OrderDetails;

Bir sorguda nerede koşulda QuantText değerini kullanabilir miyiz? örneğinSELECT OrderID, Quantity, CASE WHEN Quantity > 30 THEN "The quantity is greater than 30" WHEN Quantity = 30 THEN "The quantity is 30" ELSE "The quantity is under 30" END AS QuantityText FROM OrderDetails WHERE QuantityText = 'The quantity is 30';
Bhavin Thummar

1

Tamlık uğruna, SQL'in üç değerli mantık kullandığını ekleyebilirim. İfade:

obsolete = 'N' OR instock = 'Y'

Üç farklı sonuç verebilir:

| obsolete | instock | saleable |
|----------|---------|----------|
| Y        | Y       | true     |
| Y        | N       | false    |
| Y        | null    | null     |
| N        | Y       | true     |
| N        | N       | true     |
| N        | null    | true     |
| null     | Y       | true     |
| null     | N       | null     |
| null     | null    | null     |

Yani örneğin bir ürün kullanılmıyorsa ancak ürünün stokta olup olmadığını bilmiyorsanız, ürünün satılabilir olup olmadığını bilmiyorsunuzdur. Bu üç değerli mantığı aşağıdaki gibi yazabilirsiniz:

SELECT CASE
           WHEN obsolete = 'N' OR instock = 'Y' THEN 'true'
           WHEN NOT (obsolete = 'N' OR instock = 'Y') THEN 'false'
           ELSE NULL
       END AS saleable

Nasıl çalıştığını anladıktan sonra, null davranışına karar vererek üç sonucu iki sonuca dönüştürebilirsiniz. Örneğin, bu null değeri satılamaz olarak görür:

SELECT CASE
           WHEN obsolete = 'N' OR instock = 'Y' THEN 'true'
           ELSE 'false' -- either false or null
       END AS saleable

0

CASE deyimlerinin kullanımını seviyorum ama soru SQL Select bir IF deyimi istedi. Geçmişte kullandığım şey:

SELECT

   if(GENDER = "M","Male","Female") as Gender

FROM ...

Bir koşul ve ardından doğru koşul ve sonra yanlış koşul varsa excel veya sayfalar IF ifadeleri gibidir:

if(condition, true, false)

Ayrıca, if ifadelerini iç içe yerleştirebilirsiniz (ancak daha sonra kullanım bir CASE kullanmalıdır :-)

(Not: Bu MySQLWorkbench'te çalışır, ancak diğer platformlarda çalışmayabilir)


0

Vaka Bildirimi'ni kullanabilirsiniz:

Select 
Case WHEN (Obsolete = 'N' or InStock = 'Y') THEN 1 ELSE 0 END Saleable,
Product.*
from Product
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.