Comment effectuer un IF ... THEN dans un SQL SELECT?

Comment effectuer un IF ... THEN dans un SQL SELECT?

Comment effectuer un IF...THEN dans une instruction SQL SELECT ?

Par exemple:

SELECT IF(Obsolete = 'N' OR InStock = 'Y' ? 1 : 0) AS Saleable, * FROM Product
 
Montrez la meilleure réponse

Vous voudrez peut-être consulter ce lien . Concernant: Clauses SQL WHERE: Évitez CASE, utilisez la logique booléenne

@Quelqu'un: pas vraiment pertinent car l'article parle d'utiliser des règles de réécriture logique pour convertir une implication en disjonction. L'indice est le mot `` logique '', c'est-à-dire quelque chose qui se résout en vrai ou en faux, qui ne s'applique pas à la projection. L'article TL; DR s'applique à WHERE et CHECK mais pas à SELECT .

@ La réponse de MartinSmith est la plus élégante - utilisez IIF dans SQL 2012+.

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

Utilisez CASE. Quelque chose comme ça.

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

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

L'instruction CASE est la plus proche de IF dans SQL et est prise en charge sur toutes les versions de SQL Server.

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

Vous n'avez besoin de faire le CAST que si vous voulez que le résultat soit une valeur booléenne. Si vous êtes satisfait d'un int , cela fonctionne:

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

CASE peuvent être incorporées dans d'autres instructions CASE et même incluses dans des agrégats.

SQL Server Denali (SQL Server 2012) ajoute le Déclaration IIF , également disponible dans access ( signalé par Martin Smith ):

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

Juste un mot de prudence supplémentaire ne mettez pas vos conditions entre parenthèses lors de l'utilisation de l'étui. Il a fallu pas mal de temps pour s'en rendre compte :)

et n'oubliez pas la FIN

et le bit AS!

Case, When, Else et End devraient être en retrait parallèles (le long de la même ligne) - et seulement alors devraient être en retrait plus vers l'intérieur - fonctionne le mieux pour moi.

Avatar JMD

J'avais besoin de CAS imbriqués et j'oubliais que j'avais besoin de plusieurs END correspondants.

Bien que cela fonctionne, l'utilisation de la fonction IFF () sera la meilleure réponse

@ReeveStrife Vous voulez dire IIF() msdn.microsoft.com/en-us/library/…

@ReeveStrife uniquement si SQL Server 2012+

@ArchanMishra Salut Archan, pourriez-vous s'il vous plaît m'expliquer pourquoi vous ne devriez pas joindre vos conditions?

Méfiez-vous des sales secrets de CASE / IIF: sqlperformance.com/2014/06/t-sql-queries/…

@ArchanMishra vous le pouvez. Je pensais qu'il voulait dire que cela ralentirait les choses, mais non. Vous pouvez utiliser des crochets autant de fois que vous le souhaitez dans SQL Server, tant que cela a un sens logique pour SQL.

@DarrelMiller, vous pouvez probablement retourner TRUE ou FALSE dans l'instruction CASE et éviter le CAST, je ne sais pas si cela fonctionne sur SQL Server, mais je pense que c'est SQL. Je n'ai jamais rien vu de tel

Vous pouvez trouver de bons exemples dans La puissance des instructions CASE SQL , et je pense que la déclaration que vous pouvez utiliser sera quelque chose comme ceci (de 4guysfromrolla ):

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

voir: meta.stackexchange.com/questions/103053/… pour une discussion intéressante. Les deux liens que vous fournissez ajoutent du contexte supplémentaire, que je soutiens.

La référence est vraiment utile et fortement recommandée en cas de détails supplémentaires

Microsoft SQL Server (T-SQL)

Dans un select , utilisez:

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

Dans une clause where , utilisez:

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

pourquoi ne pas simplement faire where Obsolete = 'N' or InStock = 'Y' et couper pratiquement où

Utilisez une instruction CASE:

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

etc...
 

La déclaration de cas est votre ami dans cette situation et prend l'une des deux formes suivantes:

Le cas simple:

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

Le cas étendu:

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

Vous pouvez même mettre des instructions case dans une clause order by pour un ordre vraiment sophistiqué.

Avatar Ben

Je sais que c'est ancien, mais je pense qu'il convient de noter que vous pouvez ajouter un AS Col_Name après le END pour nommer la colonne résultante

J'ai toujours l'impression que le 2e est plus simple.

D'accord, je finis presque toujours par utiliser la déclaration de cas étendue car les conditions sur lesquelles je veux tester sont toujours plus complexes que la seule variable elle-même. Cela me semble également plus facile à lire.

Bonne explication des deux situations, avec ou sans variable. Avec la variable, la condition doit satisfaire une égalité entre la variable après l'instruction case et celle sur laquelle vous basez votre condition, sans variable, vous pouvez ajouter une condition autosuffisante à tester.

Je suis plus pratique avec la deuxième option. Les deux sont tout aussi bien.

Avatar Ken

À partir de ce lien , nous pouvons comprendre IF THEN ELSE en 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' 
 

N'est-ce pas assez bon pour T-SQL?

Ce n'est pas ce que le demandeur voulait, mais il est très utile de savoir que vous pouvez utiliser si des instructions en dehors une instruction select.

EXISTS est bon car il se libère de la boucle de recherche si un élément est trouvé. Un COUNT s'exécute jusqu'à la fin des lignes du tableau. Rien à voir avec la question, mais quelque chose à savoir.

À partir de SQL Server 2012, vous pouvez utiliser le IIF solide pour cela.

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

Ceci est en fait juste une manière abrégée (bien que non standard SQL) d'écrire CASE .

Je préfère la concision par rapport à la version étendue CASE .

Les deux IIF() et CASE se résolvent tous deux en tant qu'expressions dans une instruction SQL et ne peuvent être utilisés qu'à des endroits bien définis.

  

L'expression CASE ne peut pas être utilisée pour contrôler le flux d'exécution de   Instructions Transact-SQL, blocs d'instructions, fonctions définies par l'utilisateur et   procédures stockées.

Si vos besoins ne peuvent pas être satisfaits par ces limitations (par exemple, un besoin de renvoyer des jeux de résultats de forme différente en fonction d'une condition), SQL Server dispose également d'un IF mot-clé.

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

Il faut cependant parfois veiller à éviter les problèmes de reniflage des paramètres avec cette approche .

Cela devrait être la réponse si vous voulez une instruction IF .. then en SQL.

Si vous insérez des résultats dans une table pour la première fois, plutôt que de transférer des résultats d'une table à une autre, cela fonctionne dans 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');
 

les balises disent SQL Server, TSQL

Utilisez une logique de bits purs:

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
 

Voir démonstration de travail: si alors sans case dans SQL Server .

Pour commencer, vous devez déterminer la valeur de true et false pour les conditions sélectionnées. Voici deux NULLIF :

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

combinés ensemble donne 1 ou 0. Utilisez ensuite les opérateurs au niveau du bit .

Il s'agit de la méthode la plus WYSIWYG .

-1 pour l'obscurcissement de code. Sérieusement, c'est à peu près aussi loin que possible de WYSIWYG! Un vrai bordel illisible, et si je devais travailler sur votre code, je maudirais toute la journée ... désolé: - /

@Heliac a mis cte part dans View et vous ne verrez jamais le bordel. Pour les longs et compliqués ET, OU, ce n'est pas plus lisible que CASE (cette partie en dehors de cte bien sûr).

Je lui ai donné un +1 pour la netteté, une fois qu'il est dans un cte, mais notez que la réponse est actuellement incorrecte pour la question. Vous avez besoin d'un '|' pas un '&'.

Tout à fait d'accord avec @Heliac. Bien qu'il soit syntaxiquement correct et fonctionne correctement, il n'est tout simplement pas facilement supportable. Le placer dans un CTE ne fera que déplacer ce morceau de code illisible ailleurs.

La méthode de vérification de combinaison par table pourrait avoir ses avantages. Utiliser une variable de table et la joindre à la requête existante pourrait fournir une solution basée sur un ensemble sans casse. Cette réponse est un mauvais exemple, mais l'idée de table elle-même a du mérite.

Le lien NULLIF de Microsoft a expiré. voici un nouveau lien de travail: docs.microsoft.com/en-us/sql/t-sql/language-elements/… Mis à jour en réponse.

Pour ceux qui utilisent SQL Server 2012, IIF est une fonctionnalité qui a été ajoutée et fonctionne comme une alternative aux instructions Case.

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

Avatar jk7

Cette réponse répète (avec moins de détails) ce qui était déjà fourni dans la réponse de Martin Smith il y a plusieurs années.

SELECT CASE WHEN profile.nrefillno = 0 THEN 'N' ELSE 'R'END as newref
From profile
 

Peux-tu élaborer?

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
 

Pourriez-vous expliquer comment cela répond à la question posée?

@Guanxi: bien que ce ne soit pas ma réponse, un «cas» généralise un «si-alors-autre» (de 2 cas à plusieurs)

Peux-tu élaborer?

Instruction if-else simple dans SQL Server:

DECLARE @val INT;
SET @val = 15;

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

GO
 

Instruction Nested If ... else dans 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
 

Tard mais est-il utilisable dans SELECT comme l'OP l'a demandé?

Ce n'est pas une réponse, juste un exemple d'une instruction CASE utilisée là où je travaille. Il a une instruction CASE imbriquée. Maintenant tu sais pourquoi mes yeux sont croisés.

 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]
 

L'édition qui a reformaté les instructions Case est fine et dandy et la rend plus compréhensible, mais le SQL continuerait de se regrouper dans la vue qui l'utilise.

Je me demande simplement pourquoi CASE est voté et marqué comme une réponse au lieu du IF qui aurait dû être la réponse, comme celle-ci, c'est toujours un CASE , pas un IF .

@ Mr.J: bien que ce ne soit pas ma réponse, un «cas» généralise un «si-alors-autre» (de 2 cas à plusieurs)

Une nouvelle fonctionnalité, IIF (que nous pouvons simplement utiliser) , a été ajouté dans SQL Server 2012:

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

Avatar jk7

Cette réponse répète (avec moins de détails) ce qui était déjà fourni dans la réponse de Martin Smith il y a plusieurs années.

@ jk7 c'était la première réponse à la question.

Avatar jk7

Pas d'après ce que je vois. Il est écrit que votre réponse a été publiée le 26 avril 16 et celle de Martin le 20 juillet 2011.

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

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

Salut Surjeet Singh Bisht; votre code pourrait être correct, mais avec un certain contexte, il ferait une meilleure réponse; par exemple, vous pourriez expliquer comment et pourquoi cette modification proposée résoudrait le problème de l'interrogateur, peut-être en incluant un lien vers la documentation pertinente. Cela les rendrait plus utiles pour eux, et aussi plus utiles aux autres lecteurs de sites qui recherchent des solutions à des problèmes similaires.

Cette réponse n'ajoute rien de nouveau. En fait, cette même ligne fait partie de la réponse acceptée depuis plus de 5 ans .

De plus, il est important de mentionner que le IIF s'applique uniquement à SQL Server à partir de 2012

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

Comme solution alternative à l'instruction CASE , une approche basée sur les tables peut être utilisée:

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
 

Résultat:

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

Vendable est utilisé dans où condition dans la requête?

Il peut être utilisé dans quel état.

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

De l'avis: Welcome to Stack Overflow! Veuillez ne pas répondre uniquement avec le code source. Essayez de fournir une belle description du fonctionnement de votre solution. Voir: Comment écrire une bonne réponse? . Merci

Je pense que vous constaterez que cela ne s'exécute pas, car il manque toute sortie suivant le mot-clé 'ALORS'.

Peux-tu élaborer?

Question:

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;
 

L'utilisation d'alias - p dans ce cas - permettra d'éviter les problèmes.

Vous pouvez avoir deux choix pour que cela soit réellement implémenté:

  1. Utilisation de IIF, qui a été introduit à partir de SQL Server 2012:

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

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

Ce sera quelque chose comme ça:

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;
 

Pouvons-nous utiliser la valeur QuantityText dans quelle condition dans une requête? par exemple 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';

Par souci d'exhaustivité, j'ajouterais que SQL utilise une logique à trois valeurs. L'expression:

obsolete = 'N' OR instock = 'Y'
 

Pourrait produire trois résultats distincts:

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

Ainsi, par exemple, si un produit est obsolète mais que vous ne savez pas si le produit est en stock, vous ne savez pas si le produit est vendable. Vous pouvez écrire cette logique à trois valeurs comme suit:

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

Une fois que vous avez compris comment cela fonctionne, vous pouvez convertir trois résultats en deux résultats en décidant du comportement de null. Par exemple. cela traiterait null comme non vendable:

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