¿Cómo realizo un IF ... THEN en un SQL SELECT?

1508

¿Cómo realizo un IF...THENen una SQL SELECTdeclaración?

Por ejemplo:

SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product
Eric Labashosky
fuente
14
Es posible que desee echar un vistazo a este enlace . En cuanto a: cláusulas SQL WHERE: Evite CASO, use lógica booleana
Alguien
3
@Somebody: no es realmente relevante porque el artículo habla sobre el uso de reglas lógicas de reescritura para convertir una implicación en una disyunción. La pista es la palabra 'lógico', es decir, algo que se resuelve en verdadero o falso, que no se aplica a la proyección. TL; el artículo DR se aplica WHEREy CHECKno SELECT.
cuando
66
La respuesta de @ MartinSmith es la más elegante: use IIF en SQL 2012+.
Murray Foxcroft

Respuestas:

1760

La CASEdeclaración es la más cercana a IF en SQL y es compatible con todas las versiones de SQL Server.

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

Solo necesita hacer esto CASTsi quiere el resultado como un valor booleano. Si está satisfecho con un int, esto funciona:

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

CASElas declaraciones se pueden incrustar en otras CASEdeclaraciones e incluso se pueden incluir en agregados.

SQL Server Denali (SQL Server 2012) agrega la declaración IIF que también está disponible en acceso (señalado por Martin Smith ):

SELECT IIF(Obsolete = 'N' or InStock = 'Y', 1, 0) as Saleable, * FROM Product
Darrel Miller
fuente
57
Solo una advertencia adicional no incluya sus condiciones entre paréntesis cuando use la funda. Tomó bastante tiempo darme cuenta de eso :)
Archan Mishra
17
y no te olvides del FIN
Simon_Weaver
8
y el bit AS!
Cas Bloem
8
Caso, cuándo, Else y End deben tener sangría paralela (a lo largo de la misma línea), y solo entonces deben sangrarse más hacia adentro, funciona mejor para mí.
Ujjwal Singh
66
@ReeveStrife Only iif SQL Server 2012+
stuartdotnet
327

La declaración del caso es su amigo en esta situación, y toma una de dos formas:

El caso simple:

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

El caso extendido:

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

Incluso puede poner declaraciones de caso en un orden por cláusula para un pedido realmente elegante.

Jonathan
fuente
32
Sé que esto es antiguo, pero creo que debe tenerse en cuenta que puede agregar un AS Col_Namedespués del ENDpara nombrar la columna resultante
Ben
99
Siempre siento que el segundo es más simple.
Hogan
44
De acuerdo, casi siempre termino usando el enunciado del caso extendido porque las condiciones en las que quiero probar son siempre más complejas que solo la variable en sí. También me parece más fácil de leer.
magnum_pi
1
Buena explicación de ambas situaciones, con o sin variable. Con la variable, la condición debe satisfacer una igualdad entre la variable después de la declaración del caso y la base en la que basa su condición, sin la variable puede agregar una condición autosuficiente para probar.
Remus
Soy más conveniente con la segunda opción. Los dos están igualmente bien.
Stanley Okpala Nwosa
277

Desde SQL Server 2012 puede usar la IIFfunción para esto.

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

Esto es efectivamente solo una forma abreviada (aunque no estándar de SQL) de escritura CASE.

Prefiero la concisión en comparación con la CASEversión ampliada .

Tanto IIF()y CASEdeterminación como expresiones dentro de una instrucción SQL y sólo puede ser utilizado en lugares bien definidos.

La expresión CASE no se puede usar para controlar el flujo de ejecución de instrucciones Transact-SQL, bloques de instrucciones, funciones definidas por el usuario y procedimientos almacenados.

Si sus necesidades no pueden satisfacerse con estas limitaciones (por ejemplo, la necesidad de devolver conjuntos de resultados con formas diferentes que dependen de alguna condición), entonces SQL Server también tiene una IFpalabra clave de procedimiento .

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

Sin embargo, a veces se debe tener cuidado para evitar problemas de detección de parámetros con este enfoque .

Martin Smith
fuente
66
Esta debería ser la respuesta si desea un IF ... luego una declaración en SQL.
Mr.J
91

Puede encontrar algunos buenos ejemplos en The Power of SQL CASE Statements , y creo que la declaración que puede usar será algo como esto (de 4guysfromrolla ):

SELECT
    FirstName, LastName,
    Salary, DOB,
    CASE Gender
        WHEN 'M' THEN 'Male'
        WHEN 'F' THEN 'Female'
    END
FROM Employees
sven
fuente
44
ver: meta.stackexchange.com/questions/103053/… para una discusión interesante. Los dos enlaces que proporciona agregan un contexto adicional, que yo apoyo.
Sam Saffron
2
La referencia es realmente útil y muy recomendable en caso de detalles adicionales
baymax
75

Use CASE. Algo como esto.

SELECT Salable =
        CASE Obsolete
        WHEN 'N' THEN 1
        ELSE 0
    END
caballo pálido
fuente
50
SELECT  
(CASE 
     WHEN (Obsolete = 'N' OR InStock = 'Y') THEN 'YES'
                                            ELSE 'NO' 
 END) as Salable
, * 
FROM Product
John Sheehan
fuente
48

Microsoft SQL Server (T-SQL)

En a select, use:

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

En una wherecláusula, use:

where 1 = case when Obsolete = 'N' or InStock = 'Y' then 1 else 0 end
usuario7658
fuente
1
¿por qué no lo harías where Obsolete = 'N' or InStock = 'Y'y cortarías el por la mitad prácticamente?
maksymiuk
46

Desde este enlace , podemos entender IF THEN ELSEen 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' 

¿No es esto lo suficientemente bueno para T-SQL?

Conocer
fuente
3
Esto no es lo que el solicitante quería, pero es muy útil saber que puede usar declaraciones if fuera de una declaración select.
Jonathan
2
EXISTS es bueno porque se elimina del ciclo de búsqueda si se encuentra un elemento. COUNT se ejecuta hasta el final de las filas de la tabla. Nada que ver con preguntas, sino algo que saber.
JustJohn
45
 SELECT
   CASE 
      WHEN OBSOLETE = 'N' or InStock = 'Y' THEN 'TRUE' 
      ELSE 'FALSE' 
   END AS Salable,
   * 
FROM PRODUCT
Santiago Cepas
fuente
32

Declaración simple if-else en SQL Server:

DECLARE @val INT;
SET @val = 15;

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

GO

Sentencia anidada If ... else en 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
Ravi Anand
fuente
2
Tarde, pero ¿se puede usar en el interior SELECTcomo OP preguntó?
abdul qayyum
25

Se agregó una nueva característica, IIF (que simplemente podemos usar), en SQL Server 2012:

SELECT IIF ( (Obsolete = 'N' OR InStock = 'Y'), 1, 0) AS Saleable, * FROM Product
sandeep rawat
fuente
1
Esta respuesta repite (con menos detalles) lo que ya fue proporcionado en la respuesta por Martin Smith hace varios años.
jk7
1
@ jk7 esta fue la primera respuesta a la pregunta.
sandeep rawat el
3
No por lo que veo. Dice que su respuesta se publicó el 26 de abril de 2016 y la de Martin se publicó el 20 de julio de 2011.
jk7
24

Use una declaración CASE:

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

etc...
Krizzy
fuente
23

Use lógica de bit puro:

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

Ver demostración de trabajo: si es así sin caseSQL Server .

Para comenzar, debe calcular el valor de truey falsepara las condiciones seleccionadas. Aquí vienen dos NULLIF :

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

combinados juntos da 1 o 0. Siguiente uso de operadores bit a bit .

Es el método más WYSIWYG .

Tomásito
fuente
19
-1 para la ofuscación del código. En serio, ¡esto está tan lejos de WYSIWYG como puedas! Un desastre rojizo e ilegible, y si tuviera que trabajar en su código, estaría maldiciendo todo el día ... lo siento: - /
Heliac
2
@Heliac puso cte part en Ver y nunca verá el desorden. Para largos y complicados AND, OR, NO es más legible que CASE (esa parte fuera de cte, por supuesto).
Tomasito
1
Le di a esto un +1 para la limpieza, una vez que está en un cte, pero tenga en cuenta que la respuesta actualmente es incorrecta para la pregunta. Necesitas un '|' no un '&'.
Mark Hurd el
3
Totalmente de acuerdo con @Heliac. Si bien es sintácticamente correcto y funciona bien, simplemente no es fácilmente compatible. Ponerlo en un CTE solo moverá ese fragmento de código no legible a otro lugar.
objectNotFound
1
El método de tabla para verificar la combinación podría tener sus ventajas. Usar una variable de tabla y unirla a la consulta existente podría proporcionar una solución basada en conjuntos sin un caso. Esta respuesta es un mal ejemplo, pero la idea de la tabla en sí misma tiene mérito.
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' )
un día cuando
fuente
17
SELECT CASE WHEN profile.nrefillno = 0 THEN 'N' ELSE 'R'END as newref
From profile
atik sarker
fuente
¿Puedes elaborar?
Peter Mortensen
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
Chanukya
fuente
2
¿Podría explicarnos cómo responde esto a la pregunta?
Guanxi
@Guanxi: aunque no es mi respuesta, un 'caso' generaliza un 'si-entonces-otro' (de 2 casos a muchos)
JosephDoggie
¿Puedes elaborar?
Peter Mortensen
13

Esta no es una respuesta, solo un ejemplo de una declaración CASE en uso donde trabajo. Tiene una declaración CASE anidada. Ahora sabes por qué mis ojos están cruzados.

 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]
JustJohn
fuente
1
La edición que volvió a formatear las declaraciones de Case está bien y es elegante y lo hace más comprensible, pero el SQL aún se acumularía en la vista que lo está usando.
JustJohn
1
Solo estoy divagando por qué CASEser votado y marcado como una respuesta en lugar de la IFque debería haber sido la respuesta, como esta, esta sigue siendo una CASEdeclaración, no una IF.
Mr.J
@ Mr.J: aunque no es mi respuesta, un 'caso' generaliza un 'si-entonces-otro' (de 2 casos a muchos)
JosephDoggie
12

Si está insertando resultados en una tabla por primera vez, en lugar de transferir resultados de una tabla a otra, esto funciona en 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');
Robert B. Grossman
fuente
44
las etiquetas dicen SQL Server, TSQL
Malachi
11

Como una solución alternativa a la CASEdeclaración, se puede utilizar un enfoque basado en tablas:

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

Resultado:

ID          Obsolete   InStock    Saleable
----------- ---------- ---------- -----------
1           N          Y          1
2           A          B          0
3           N          B          1
4           A          Y          1
Serkan Arslan
fuente
¿Se puede vender en condiciones de consulta?
Bhavin Thummar el
Se puede usar en donde condición.
Serkan Arslan
9
SELECT CASE WHEN Obsolete = 'N' or InStock = 'Y' THEN 1 ELSE 0 
             END AS Saleable, * 
FROM Product

fuente
6

Para aquellos que usan SQL Server 2012, IIF es una característica que se ha agregado y funciona como una alternativa a las declaraciones de casos.

SELECT IIF(Obsolete = 'N' OR InStock = 'Y', 1, 0) AS Salable, *
FROM   Product 
Dibin
fuente
1
Esta respuesta repite (con menos detalles) lo que ya fue proporcionado en la respuesta por Martin Smith hace varios años.
jk7
6
  SELECT IIF(Obsolete = 'N' OR InStock = 'Y',1,0) AS Saleable, * FROM Product
SURJEET SINGH Bisht
fuente
77
Hola surjeet singh bisht; su código puede ser correcto, pero con algún contexto sería una mejor respuesta; por ejemplo, podría explicar cómo y por qué este cambio propuesto resolvería el problema del interlocutor, tal vez incluyendo un enlace a la documentación relevante. Eso lo haría más útil para ellos, y también más útil para otros lectores del sitio que buscan soluciones a problemas similares.
Vince Bowdren
55
Esta respuesta no agrega nada nuevo. De hecho, esta misma línea ha sido parte de la respuesta aceptada durante más de 5 años .
SL Barth - Restablece a Mónica el
1
Además, es importante mencionar que el IIF solo se aplica a SQL Server a partir de 2012
Ivan Rascon
5

Puede tener dos opciones para implementar esto realmente:

  1. Usando IIF, que se introdujo desde SQL Server 2012:

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

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

Pregunta:

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;

El uso de alias, pen este caso, ayudará a prevenir problemas.

David Cohn
fuente
3

Usar SQL CASE es como las declaraciones normales If / Else. En la consulta a continuación, si el valor es obsoleto = 'N' o si el valor de InStock = 'Y', la salida será 1. De lo contrario, la salida será 0. Luego colocamos ese valor 0 o 1 debajo de la columna vendible.

SELECT
      CASE 
        WHEN obsolete = 'N' OR InStock = 'Y' 
        THEN 1 
        ELSE 0 
      END AS Salable
      , * 
FROM PRODUCT
Tharuka
fuente
1
Suena bien. Tal vez una o dos palabras para explicarlo?
JQSOFT
Es como las declaraciones normales de If / Else. Si el valor es obsoleto = 'N' o si el valor InStock = 'Y', la salida será 1. De lo contrario, la salida será 0.
Tharuka
1
Gracias. Por favor Editar tu post para agregar esta explicación. Me gusta: El If..Then...Else..uso de las declaraciones de la SQLsiguiente manera ...
JQSOFT
2
SELECT 
  CAST(
    CASE WHEN Obsolete = 'N' 
    or InStock = 'Y' THEN ELSE 0 END AS bit
  ) as Saleable, * 
FROM 
  Product
gii96
fuente
8
De la opinión: Bienvenido a Stack Overflow! Por favor no responda solo con el código fuente. Intente proporcionar una buena descripción sobre cómo funciona su solución. Ver: ¿Cómo escribo una buena respuesta? . Gracias
sɐunıɔ ןɐ qɐp
3
Creo que encontrará que esto no se ejecuta, porque le falta algún resultado después de la palabra clave 'ENTONCES'.
Dodecaphone
¿Puedes elaborar?
Peter Mortensen
2

Será algo así:

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;
Muhammad Awais
fuente
¿Podemos usar el valor de CantidadTexto en la condición where en una consulta? por ejemploSELECT 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, el
1

En aras de la exhaustividad, agregaría que SQL utiliza la lógica de tres valores. La expresion:

obsolete = 'N' OR instock = 'Y'

Podría producir tres resultados distintos:

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

Entonces, por ejemplo, si un producto es obsoleto pero no sabe si el producto es instock, entonces no sabe si el producto es vendible. Puede escribir esta lógica de tres valores de la siguiente manera:

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

Una vez que descubra cómo funciona, puede convertir tres resultados en dos resultados al decidir el comportamiento de nulo. Por ejemplo, esto trataría nulo como no vendible:

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

Me gusta el uso de las declaraciones CASE pero la pregunta solicitó una declaración IF en SQL Select. Lo que he usado en el pasado ha sido:

SELECT

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

FROM ...

Es como las declaraciones IF de Excel o de hojas donde hay un condicional seguido de la condición verdadera y luego la condición falsa:

if(condition, true, false)

Además, puede anidar las declaraciones if (pero luego use debería usar un CASE :-)

(Nota: esto funciona en MySQLWorkbench pero puede no funcionar en otras plataformas)

Prashant Marathay
fuente
0

Puede usar la Declaración de caso:

Select 
Case WHEN (Obsolete = 'N' or InStock = 'Y') THEN 1 ELSE 0 END Saleable,
Product.*
from Product
akanksha gupta
fuente