Bagaimana cara melakukan JIKA ... KEMUDIAN dalam SQL SELECT?


1508

Bagaimana cara melakukan IF...THENdalam sebuah SQL SELECTpernyataan?

Sebagai contoh:

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

14
Anda mungkin ingin melihat tautan ini . Mengenai: SQL WHERE klausa: Hindari KASUS, gunakan logika Boolean
Seseorang

3
@ Seseorang: tidak benar-benar relevan karena artikel tersebut berbicara tentang penggunaan aturan penulisan ulang logis untuk mengubah implikasi menjadi disjungsi. Petunjuknya adalah kata 'logis' yaitu sesuatu yang memutuskan benar atau salah, yang tidak berlaku untuk proyeksi. TL; Artikel DR berlaku untuk WHEREdan CHECKtetapi tidak SELECT.
onedaywhen

6
@ MartinSmith menjawab adalah yang paling elegan - gunakan IIF di SQL 2012+.
Murray Foxcroft

Jawaban:


1760

The CASEpernyataan adalah yang paling dekat dengan IF di SQL dan didukung pada semua versi SQL Server.

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

Anda hanya perlu melakukan CASTjika Anda menginginkan hasilnya sebagai nilai Boolean. Jika Anda senang dengan int, ini berfungsi:

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

CASEpernyataan dapat disematkan dalam CASEpernyataan lain dan bahkan dimasukkan dalam agregat.

SQL Server Denali (SQL Server 2012) menambahkan pernyataan IIF yang juga tersedia dalam akses (ditunjukkan oleh Martin Smith ):

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

57
Hanya kata peringatan tambahan jangan lampirkan kondisi Anda dalam tanda kurung saat menggunakan kasing. Butuh sedikit waktu untuk menyadarinya :)
Archan Mishra

17
dan jangan lupa AKHIR
Simon_Weaver

8
dan AS sedikit!
Cas Bloem

8
Case, When, Else dan End harus diberi indentasi paralel (sepanjang garis yang sama) - dan hanya kemudian harus di indentasi lebih dalam - bekerja paling baik untuk saya.
Ujjwal Singh

6
@ReeveStrife Only iif SQL Server 2012+
stuartdotnet

327

Pernyataan kasus adalah teman Anda dalam situasi ini, dan mengambil salah satu dari dua bentuk:

Kasus sederhana:

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

Kasus diperpanjang:

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

Anda bahkan dapat memasukkan pernyataan kasus dalam urutan dengan klausa untuk pemesanan yang benar-benar mewah.


32
Saya tahu ini sudah tua, tetapi saya rasa perlu dicatat bahwa Anda dapat menambahkan AS Col_Namesetelah ENDuntuk memberi nama kolom yang dihasilkan
Ben

9
Saya selalu merasa yang ke-2 lebih sederhana.
Hogan

4
Setuju, saya hampir selalu berakhir dengan menggunakan pernyataan kasus diperpanjang karena kondisi yang ingin saya uji selalu lebih kompleks daripada hanya satu variabel itu sendiri. Saya juga merasa lebih mudah untuk membaca.
magnum_pi

1
Penjelasan yang baik dari kedua situasi, dengan atau tanpa variabel. Dengan variabel kondisi perlu memenuhi kesetaraan antara variabel setelah pernyataan kasus dan yang Anda mendasari kondisi Anda, tanpa variabel Anda dapat menambahkan kondisi mandiri untuk menguji.
Remus.

Saya lebih nyaman dengan opsi kedua. Keduanya sama-sama baik-baik saja.
Stanley Okpala Nwosa

277

Dari SQL Server 2012 Anda dapat menggunakan IIFfungsi untuk ini.

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

Ini secara efektif hanya cara penulisan (walaupun bukan SQL standar) penulisan CASE.

Saya lebih suka keringkasan jika dibandingkan dengan CASEversi yang diperluas .

Keduanya IIF()dan CASEdiselesaikan sebagai ekspresi dalam pernyataan SQL dan hanya dapat digunakan di tempat yang didefinisikan dengan baik.

Ekspresi CASE tidak dapat digunakan untuk mengontrol aliran eksekusi pernyataan Transact-SQL, blok pernyataan, fungsi yang ditentukan pengguna, dan prosedur tersimpan.

Jika kebutuhan Anda tidak dapat dipenuhi oleh batasan-batasan ini (misalnya, kebutuhan untuk mengembalikan set hasil yang berbeda tergantung pada beberapa kondisi) maka SQL Server juga memiliki IFkata kunci prosedural .

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

Namun terkadang harus diperhatikan untuk menghindari masalah parameter sniffing dengan pendekatan ini .


6
Ini harus menjadi jawaban jika Anda menginginkan pernyataan IF .. lalu dalam SQL.
Mr.J

91

Anda dapat menemukan beberapa contoh yang bagus dalam Kekuatan Pernyataan KASUS SQL , dan saya pikir pernyataan yang dapat Anda gunakan akan menjadi sesuatu seperti ini (dari 4guysfromrolla ):

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

4
lihat: meta.stackexchange.com/questions/103053/... untuk diskusi yang menarik. Saya dua tautan yang Anda berikan memang menambah konteks ekstra, yang saya dukung.
Sam Saffron

2

75

Gunakan KASUS. Sesuatu seperti ini.

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)

Dalam select, gunakan:

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

Dalam sebuah whereklausa, gunakan:

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

1
kenapa tidak Anda lakukan saja where Obsolete = 'N' or InStock = 'Y'dan memotong di mana setengah praktis
maksymiuk

46

Dari tautan ini , kita dapat memahami IF THEN ELSEdalam T-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' 

Bukankah ini cukup baik untuk T-SQL?


3
Ini bukan yang diinginkan pemohon, tetapi sangat berguna untuk mengetahui bahwa Anda dapat menggunakan pernyataan jika di luar pernyataan pilih.
Jonathan

2
EXISTS bagus karena ia keluar dari loop pencarian jika item ditemukan. COUNT berjalan hingga akhir baris tabel. Tidak ada hubungannya dengan pertanyaan, tetapi ada sesuatu yang perlu diketahui.
JustJohn

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

32

Pernyataan if-else sederhana di SQL Server:

DECLARE @val INT;
SET @val = 15;

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

GO

Pernyataan bersarang jika ... di SQL Server -

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
Terlambat tetapi apakah itu bisa digunakan di dalam SELECTseperti yang diminta OP?
abdul qayyum

25

Fitur baru, IIF (yang bisa kita gunakan), ditambahkan di SQL Server 2012:

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

1
Jawaban ini berulang (dengan kurang detail) apa yang sudah disediakan dalam jawaban oleh Martin Smith beberapa tahun lalu.
jk7

1
@ jk7 ini adalah jawaban pertama untuk pertanyaan itu.
sandeep rawat

3
Bukan dari apa yang saya lihat. Katanya jawaban Anda diposting 26 Apr '16 dan Martin's diposting 20 Juli 11.
jk7

24

Gunakan pernyataan KASUS:

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

etc...

23

Gunakan logika bit murni:

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

Lihat demo yang berfungsi: jika kemudian tanpa casedi SQL Server .

Untuk memulai, Anda perlu menghitung nilai truedan falseuntuk kondisi yang dipilih. Inilah dua NULLIF :

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

dikombinasikan bersama memberikan 1 atau 0. Selanjutnya gunakan operator bitwise .

Ini adalah metode yang paling WYSIWYG .


19
-1 untuk Kebingungan Kode. Serius, ini tentang sejauh WYSIWYG yang Anda bisa! Kekacauan yang tidak dapat dibaca, dan jika saya harus mengerjakan kode Anda, saya akan mengutuk sepanjang hari ... maaf: - /
Heliac

2
@Heliac menempatkan bagian cte di View dan Anda tidak akan pernah melihat kekacauan. Untuk AND yang panjang dan rumit, ATAU, BUKAN itu lebih mudah dibaca daripada KASUS (bagian di luar cte tentu saja).
Tomasito

1
Saya telah memberikan ini +1 untuk kerapian, begitu itu dalam cte, tetapi perhatikan bahwa jawabannya saat ini salah untuk pertanyaan. Anda membutuhkan '|' bukan '&'.
Mark Hurd

3
Sepenuhnya setuju dengan @Heliac. Meskipun secara sintaksis benar dan berfungsi dengan baik itu tidak mudah didukung. Menempatkannya dalam CTE hanya akan memindahkan potongan kode yang tidak dapat dibaca di tempat lain.
objectNotFound

1
Metode tabel untuk memeriksa kombinasi dapat memiliki kelebihan. Menggunakan variabel tabel dan bergabung dengan kueri yang ada dapat memberikan solusi berbasis set tanpa case. Jawaban ini adalah contoh yang buruk, tetapi ide tabel itu sendiri pantas.
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
Bisakah Anda memberikan penjelasan tentang bagaimana ini menjawab pertanyaan yang diajukan?
Guanxi

@ Guanxi: meskipun bukan jawaban saya, sebuah 'kasus' menggeneralisasi 'jika-maka-lain' (dari 2 kasus ke banyak)
JosephDoggie

Bisakah Anda menguraikan?
Peter Mortensen

13

Ini bukan jawaban, hanya contoh pernyataan KASUS yang digunakan tempat saya bekerja. Ini memiliki pernyataan KASUS bersarang. Sekarang Anda tahu mengapa mata saya juling.

 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
Hasil edit yang memformat ulang pernyataan Kasus semuanya baik dan keren dan membuatnya lebih dimengerti tetapi SQL masih akan lumpuh dalam tampilan yang menggunakannya.
JustJohn

1
Saya hanya mengembara mengapa CASEmenjadi terangkat dan ditandai sebagai jawaban alih-alih IFyang seharusnya menjadi jawaban, seperti ini, ini masih merupakan CASEpernyataan, bukan sebuah IF.
Mr.J

@ Mr.J: meskipun bukan jawaban saya, sebuah 'kasus' menggeneralisasi 'jika-maka-lain' (dari 2 kasus ke banyak)
JosephDoggie

12

Jika Anda memasukkan hasil ke dalam tabel untuk pertama kalinya, alih-alih mentransfer hasil dari satu tabel ke tabel lainnya, ini berfungsi di Oracle 11.2g:

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
tag mengatakan SQL Server, TSQL
Maleakhi

11

Sebagai solusi alternatif untuk CASEpernyataan tersebut, pendekatan berbasis tabel dapat digunakan:

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

Hasil:

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

Laku digunakan di mana kondisi dalam permintaan?
Bhavin Thummar

Dapat digunakan dalam kondisi di mana.
Serkan Arslan

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

6

Bagi mereka yang menggunakan SQL Server 2012, IIF adalah fitur yang telah ditambahkan dan berfungsi sebagai alternatif untuk pernyataan Kasus.

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

1
Jawaban ini berulang (dengan kurang detail) apa yang sudah disediakan dalam jawaban oleh Martin Smith beberapa tahun lalu.
jk7

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

7
Hai Surjeet Singh Bisht; kode Anda mungkin benar, tetapi dengan beberapa konteks itu akan membuat jawaban yang lebih baik; misalnya, Anda dapat menjelaskan bagaimana dan mengapa perubahan yang diajukan ini akan menyelesaikan masalah si penanya, mungkin termasuk tautan ke dokumentasi yang relevan. Itu akan membuatnya lebih bermanfaat bagi mereka, dan juga lebih bermanfaat bagi pembaca situs lain yang mencari solusi untuk masalah yang sama.
Vince Bowdren

5
Jawaban ini tidak menambahkan sesuatu yang baru. Faktanya, baris yang sama persis ini telah menjadi bagian dari jawaban yang diterima selama lebih dari 5 tahun .
SL Barth - Pasang kembali Monica

1
Selain itu penting untuk menyebutkan bahwa IIF hanya berlaku untuk SQL Server dimulai dengan 2012
Ivan Rascon

5

Anda dapat memiliki dua pilihan untuk menerapkan ini:

  1. Menggunakan IIF, yang diperkenalkan dari SQL Server 2012:

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

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

4

Pertanyaan:

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;

Menggunakan alias - pdalam hal ini - akan membantu mencegah masalah.


3

Menggunakan SQL CASE sama seperti pernyataan If / Else biasa. Dalam kueri di bawah ini, Jika nilai usang = 'N' atau Jika nilai InStock = 'Y' maka Output akan menjadi 1. Jika tidak, output akan menjadi 0. Kemudian kita menempatkan nilai 0 atau 1 di bawah kolom Salable.

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

1
Kedengarannya bagus. Mungkin satu atau dua kata untuk menjelaskannya?
JQSOFT

Ini seperti pernyataan If / Else yang normal. Jika nilai usang = 'N' atau Jika nilai InStock = 'Y' maka Output akan menjadi 1. Jika tidak, output akan menjadi 0.
Tharuka

1
Terima kasih. Silakan Edit posting Anda untuk menambahkan penjelasan ini. Seperti: If..Then...Else..Pernyataan penggunaan dalam SQLsebagai berikut ....
JQSOFT

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

8
Dari Ulasan: Welcome to Stack Overflow! Tolong jangan jawab hanya dengan kode sumber. Cobalah untuk memberikan deskripsi yang bagus tentang cara kerja solusi Anda. Lihat: Bagaimana saya menulis jawaban yang baik? . Terima kasih
sɐunıɔ ןɐ qɐp

3
Saya pikir Anda akan menemukan ini tidak dijalankan, karena tidak ada output yang mengikuti kata kunci 'LALU'.
Dodecaphone

Bisakah Anda menguraikan?
Peter Mortensen

2

Ini akan menjadi sesuatu seperti itu:

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;

Bisakah kita menggunakan nilai QuantityText di mana kondisi dalam kueri? misalnyaSELECT 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

Demi kelengkapan, saya akan menambahkan bahwa SQL menggunakan logika bernilai tiga. Ekspresi:

obsolete = 'N' OR instock = 'Y'

Dapat menghasilkan tiga hasil berbeda:

| 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     |

Jadi misalnya jika suatu produk sudah usang tetapi Anda tidak tahu apakah produk tersebut tidak berharga maka Anda tidak tahu apakah produk itu dapat dijual. Anda dapat menulis logika tiga nilai ini sebagai berikut:

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

Setelah Anda mengetahui cara kerjanya, Anda bisa mengonversi tiga hasil menjadi dua hasil dengan memutuskan perilaku nol. Misalnya ini akan memperlakukan null sebagai tidak terjual:

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

0

Saya suka menggunakan pernyataan KASUS tetapi pertanyaannya meminta pernyataan IF di Pilih SQL. Apa yang saya gunakan di masa lalu adalah:

SELECT

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

FROM ...

Ini seperti pernyataan excel atau sheet IF di mana ada kondisi yang diikuti oleh kondisi sebenarnya dan kemudian kondisi salah:

if(condition, true, false)

Selain itu, Anda dapat membuat pernyataan if (tetapi kemudian gunakan harus menggunakan KASUS :-)

(Catatan: ini berfungsi di MySQLWorkbench tetapi mungkin tidak berfungsi di platform lain)


0

Anda dapat menggunakan Pernyataan Kasus:

Select 
Case WHEN (Obsolete = 'N' or InStock = 'Y') THEN 1 ELSE 0 END Saleable,
Product.*
from Product
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.