Як мені виконати ЯКЩО… ТОГО в SQL SELECT?


1508

Як мені виконати IF...THENв SQL SELECTзаяві?

Наприклад:

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

14
Ви можете поглянути за цим посиланням . Щодо: SQL WHERE пункти: Уникайте CASE, використовуйте логічну логіку
хтось

3
@ Хтось: не дуже актуально, оскільки в статті йдеться про використання логічних правил переписання для перетворення імплікації в диз'юнкцію. Підказкою є слово "логічне", тобто те, що вирішується на істинне чи хибне, що не стосується проекції. Стаття TL; DR стосується WHEREта CHECKне відповідає SELECT.
день, коли

6
@ Відповідь MartinSmith є найвишуканішою - використовуйте IIF у SQL 2012+.
Мюррей Фокскрофт

Відповіді:


1760

CASEЗатвердження ближче до ПЧ в SQL і підтримується на всіх версіях SQL Server.

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

Виконувати це потрібно лише в тому CASTвипадку, якщо результат бажаний як булеве значення. Якщо ви задоволені int, це працює:

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

CASEзаяви можна вбудовувати в інші CASEтвердження і навіть включати в сукупності.

SQL Server Denali (SQL Server 2012) додає оператор IIF, який також доступний у доступі (вказав Мартін Сміт ):

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

57
Просто додаткове слово обережності не вкладайте ваші умови в брекети під час використання корпусу. Знадобилося зовсім небагато часу, щоб зрозуміти це :)
Архан Мішра

17
і не забудьте кінець
Simon_Weaver

8
і AS біт!
Cas Bloem

8
Випадок "Коли", "Ельзе" та "Кінець" слід відрізати паралельно (уздовж однієї лінії) - і лише тоді слід відступати далі всередину - для мене найкраще працює.
Ujjwal Singh

6
@ReeveStrife Тільки iif SQL Server 2012+
stuartdotnet

327

Заява справи є вашим другом у цій ситуації та має одну з двох форм:

Простий випадок:

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

Розширений випадок:

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

Ви навіть можете розміщувати випадок справ у порядку, за допомогою пункту дійсного замовлення.


32
Я знаю, що це по-старому, але я думаю, що слід зазначити, що ви можете додати AS Col_Nameпісля цього, ENDщоб назвати отриманий стовпець
Бен

9
Я завжди відчуваю, що 2-й простіший.
Хоган

4
Погоджений, я майже завжди користуюся розширеним твердженням справи, оскільки умови, на які я хочу перевірити, завжди складніші, ніж просто одна змінна. Мені просто просто легше читати.
magnum_pi

1
Гарне пояснення обох ситуацій, зі змінною чи без. За допомогою змінної умова повинна задовольняти рівність між змінною після заяви справи та тією, на якій ви базуєте свою умову, без змінної ви можете додати самодостатню умову для тестування.
Рем.А

Мені зручніше з другим варіантом. Двоє однаково добре.
Стенлі Окпала Нвоса

277

З SQL Server 2012 ви можете використовувати для цього IIFфункцію .

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

Це фактично лише короткий (хоч і не стандартний SQL) спосіб написання CASE.

Я віддаю перевагу стислість у порівнянні з розширеною CASEверсією.

Обидва IIF()і CASEвирішуються як вирази в операторі SQL і можуть використовуватися лише у чітко визначених місцях.

Вираз CASE не може використовуватися для управління потоком виконання операторів Transact-SQL, блоків операторів, визначених користувачем функцій та збережених процедур.

Якщо ваші потреби не можуть бути задоволені цими обмеженнями (наприклад, потреба повертати різні форми наборів результатів залежно від певної умови), то у SQL Server є також IFключове слово процедурне .

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

Іноді потрібно бути обережним, щоб уникнути проблем з обнюхуванням параметрів при такому підході .


6
Це має бути відповіддю, якщо ви хочете IF .., а потім оператор у SQL.
Містер Дж.

91

Ви можете знайти кілька прикладних прикладів у The Power of SQL CASE Заяви , і я думаю, що твердження, яке ви можете використовувати, буде чимось подібним (від 4guysfromrolla ):

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

4
дивіться: meta.stackexchange.com/questions/103053/… для цікавої дискусії. Я, два надані вами посилання, додають додатковий контекст, який я підтримую.
Сем Шафрон




48

Microsoft SQL Server (T-SQL)

У програмі selectвикористовуйте:

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

У whereпункті використовуйте:

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

1
чому б ти просто не робив where Obsolete = 'N' or InStock = 'Y'і скорочував куди навпіл практично
maksymiuk

46

За цим посиланням ми можемо зрозуміти IF THEN ELSEв 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' 

Хіба це недостатньо добре для T-SQL?


3
Це не те, що хотів запитувач, але дуже корисно знати, що ви можете використовувати, якщо оператори поза вибраним оператором.
Джонатан

2
EXISTS хороший тим, що він виходить із циклу пошуку, якщо предмет знайдено. COUNT працює до кінця рядків таблиці. Нічого спільного з питанням, але щось знати.
JustJohn


32

Просте твердження if-else в SQL Server:

DECLARE @val INT;
SET @val = 15;

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

GO

Вкладений If ... else оператор у 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
Пізно, але чи можна використовувати всередині, SELECTяк просили ОП?
abdul qayyum

25

У SQL Server 2012 була додана нова функція - IIF (яку ми можемо просто використовувати):

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

1
Ця відповідь повторює (з меншою деталізацією) те, що вже було надано у відповіді Мартіном Смітом кілька років тому.
jk7

1
@ jk7 це була перша відповідь на питання.
sandeep rawat

3
Не з того, що я бачу. У ньому сказано, що ваша відповідь була опублікована 26 квітня 16 року, а Мартіна була опублікована 20 липня '11.
jk7

24

Використовуйте оператор CASE:

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

etc...

23

Використовуйте чисту бітну логіку:

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

Дивіться робочу демонстрацію: якщо тоді без caseSQL Server .

Для початку вам потрібно визначити значення trueта falseвибрані умови. Ось два NULLIF :

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

об'єднані разом дають 1 або 0. Далі використовують побітові оператори .

Це самий метод WYSIWYG .


19
-1 для кодової обтурації. Серйозно, це далеко не WYSIWYG, як ви можете отримати!
Грубий нечитний

2
@Heliac поставив cte участь у View, і ти ніколи не побачиш безлад. Для довгого і складного І, АБО, НЕ, це читабельніше, ніж CASE (ця частина поза cte звичайно).
Томасіто

1
Я дав цю оцінку +1 для акуратності, як тільки вона знаходиться в cte, але зауважте, що відповідь на даний момент не відповідає питанню. Вам потрібно '|' не '&'.
Марк Херд

3
Повністю згоден з @Heliac. Хоча це синтаксично правильно і працює добре, це просто не легко підтримувати. Якщо помістити його в CTE, просто перемістіть цей фрагмент нечитабельного коду кудись ще.
objectNotFound

1
Табличний спосіб перевірки комбінації може мати свої переваги. Використання змінної таблиці та приєднання її до вже наявного запиту може забезпечити рішення на основі набору без випадку. Ця відповідь є поганим прикладом, але сама ідея таблиці має заслугу.
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
Не могли б ви пояснити, як це відповідає на поставлене запитання?
Гуансі

@Guanxi: хоч це не моя відповідь, "випадок" узагальнює "якщо-то-то" (від 2 випадків до багатьох)
JosephDoggie

Чи можете ви докладно?
Пітер Мортенсен

13

Це не відповідь, а лише приклад заяви CASE, яка використовується там, де я працюю. Він має вкладений оператор CASE. Тепер ви знаєте, чому мені схрещені очі.

 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, все добре і безглуздо, і робить його більш зрозумілим, але все ж SQL все одно з'явиться в уявленні, яке ним використовується.
JustJohn

1
Я просто CASEблукаю, чому став наголошеним і позначений як відповідь замість того, на IFщо мав би бути відповідь, як ця, це все-таки CASEтвердження, а не відповідь IF.
Містер Дж.

@ Mr.J: хоч це не моя відповідь, "випадок" узагальнює "якщо тоді" (від 2 випадків до багатьох)
JosephDoggie

12

Якщо ви вставляєте результати в таблицю вперше, а не переносите результати з однієї таблиці в іншу, це працює в 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
теги кажуть, що SQL Server, TSQL
Малахій

11

В якості альтернативного рішення CASEтвердження можна використовувати підхід, керований таблицею:

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

Результат:

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

Salable використовується в тому випадку, коли стан запиту?
Bhavin Thummar

Він може бути використаний в умовах, коли це.
Серкан Арслан

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


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

7
Привіт Суржіет Сінгх Біш; ваш код може бути правильним, але з деяким контекстом він би краще відповів; наприклад, ви можете пояснити, як і чому ця запропонована зміна вирішить проблему запитувача, можливо, включивши посилання на відповідну документацію. Це зробило б їх більш корисним, а також кориснішим для інших читачів сайтів, які шукають рішення подібних проблем.
Вінс Боудрен

5
Ця відповідь не додає нічого нового. Насправді цей саме той самий рядок був частиною прийнятої відповіді вже більше 5 років .
SL Barth - Відновіть Моніку

1
Крім того, важливо зазначити, що IIF застосовується лише до SQL Server, починаючи з 2012 року
Іван Раскон

5

Для цього реально реалізувати два варіанти:

  1. Використовуючи IIF, представлений із SQL Server 2012:

    SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
  2. Використання Select Case:

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

4

Питання:

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;

Використання псевдонімів - pу цьому випадку - допоможе запобігти проблемам.


3

Використання SQL CASE подібно до звичайних операторів If / Else. У нижченаведеному запиті, якщо застаріле значення = 'N' або Якщо InStock значення = 'Y', то вихід буде дорівнює 1. В іншому випадку виведення буде 0. Тоді ми помістимо це значення 0 або 1 під стовпчик Salable.

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

1
Звучить добре. Може, слово чи два, щоб пояснити це?
JQSOFT

Це як звичайні твердження If / Else. Якщо застаріле значення = 'N' або Якщо значення InStock = 'Y', то вихід буде
рівним

1
Дякую. Будь ласка, відредагуйте свою публікацію, щоб додати це пояснення. Як: Використання If..Then...Else..тверджень у SQLнаступному ....
JQSOFT

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

8
З огляду: Ласкаво просимо в стек переповнення! Не відповідайте лише вихідним кодом. Спробуйте надати приємний опис про те, як працює ваше рішення. Дивіться: Як написати гарну відповідь? . Дякую
sɐunıɔ ןɐ qɐp

3
Я думаю, що ви виявите, що це не виконується, оскільки в ньому відсутній вихід після ключового слова "THEN".
Додекафон

Чи можете ви докладно?
Пітер Мортенсен

2

Це буде щось подібне:

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;

Чи можемо ми використати значення QuantityText у тому випадку, коли умова у запиті? наприклад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 WHERE QuantityText = 'The quantity is 30';
Thummar Bhavin

1

Для повноти я додам, що SQL використовує тризначну логіку. Вираз:

obsolete = 'N' OR instock = 'Y'

Може дати три чіткі результати:

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

Так, наприклад, якщо продукт є застарілим, але ви не знаєте, чи товар є на складі, то ви не знаєте, чи товар продається. Ви можете записати цю тризначну логіку наступним чином:

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

Як тільки ви зрозумієте, як це працює, ви можете перетворити три результати на два результати, вирішивши поведінку нуля. Наприклад, це вважатиметься недійсним як неподатливим:

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

0

Мені подобається використання операторів CASE, але в питанні було задано оператор IF у SQL Select. Що я раніше використовував:

SELECT

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

FROM ...

Це як у висловлюваннях excel або аргументи IF, коли існує умовна передумова справжньої умови, а потім хибна умова:

if(condition, true, false)

Крім того, ви можете вкласти оператори if (але тоді для використання слід використовувати CASE :-)

(Примітка. Це працює в MySQLWorkbench, але може не працювати на інших платформах)


0

Ви можете використовувати заяву:

Select 
Case WHEN (Obsolete = 'N' or InStock = 'Y') THEN 1 ELSE 0 END Saleable,
Product.*
from Product
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.