IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Vérifier une clause à 3 cas de figure dont 2 In


Sujet :

Langage SQL

  1. #1
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2024
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2024
    Messages : 47
    Par défaut Vérifier une clause à 3 cas de figure dont 2 In
    Bonjour,

    J'ai encore un souci avec une requête qui va servir à la génération d'un rapport (MS Report builder).

    Les parties SELECT et FROM sont OK, j'ai les bons noms de tables et les colonnes correspondant aux informations que je dois récupérer.

    Le point qui m'ennuie est une des clauses dans le WHERE.
    J'ai un des paramètres en entrée, que j'ai appelé @TypeTravail, qui pourra prendre une (seule et unique) valeur parmi ces 3 : Routage, Autres, Tous.
    Dans le cas où @TypeTravail est Routage, je dois vérifier la condition B1.ResourceType IN ('RO', 'RP', 'RU');
    Si @TypeTravail est Autres, cette fois je dois vérifier B1.ResourceType NOT IN ('RO', 'RP', 'RU');
    Et si @TypeTravail est Tous, je n'ai pas besoin de filtrer B1.ResourceType, donc je pensais juste vérifier une clause B1.ResourceType <> '' pour contrôler que la colonne ne soit pas vide (l'ERP ne permet pas d'avoir une valeur vide pour cette colonne).

    Mon code actuel est rédigé de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    AND (CASE WHEN @TypeTravail = 'Routage' THEN B1. ResourceType IN ('RO', 'RP', 'RU')
    		 ELSE WHEN  @TypeTravail = 'Autres' THEN B1. ResourceType NOT IN ('RO', 'RP', 'RU')
    		 ELSE B1.ResourceType <> '' END)
    Mais SQL Server Management Studio me reproche une syntaxe incorrecte : Incorrect syntax near the keyword 'IN'

    J'ai fait un 2eme essai pour retirer la partie "IN" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    AND (CASE WHEN @TypeTravail = 'Routage' THEN (B1. ResourceType = 'RO'OR B1.ResourceType = 'RP' OR B1.ResourceType =  'RU')
    		 ELSE WHEN  @TypeTravail = 'Autres' THEN (B1.ResourceType <> 'RO' AND B1.ResourceType <> 'RP'AND B1.ResourceType <>  'RU')
    		 ELSE B1.ResourceType <> '' END)
    Réponse de SSMS : Incorrect syntax near '='

    Dans les deux cas, la ligne concernée est celle où mon CASE commence.

    Quelle méthode pourrais-je utiliser pour pouvoir vérifier ces conditions?
    Merci d'avance pour vos lumières

  2. #2
    Expert confirmé
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 366
    Par défaut
    Bonjour,
    Tu peux remplacer le CASE par une simple "combinaison):
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ...
    AND ((@TypeTravail = 'Routage' AND B1. ResourceType IN ('RO', 'RP', 'RU'))
    OR (@TypeTravail = 'Autres' AND B1. ResourceType NOT IN ('RO', 'RP', 'RU'))
    OR (@TypeTravail not in ('Routage','Autres') and B1.ResourceType <> ''))

    Tatayo.

  3. #3
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2024
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2024
    Messages : 47
    Par défaut
    Bonjour Tatayo,

    Merci, cette fois la requête passe

    Je passe la question en résolu, je n'ai plus qu'à vérifier que les résultats sont bien ceux qu'il me faut.

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 984
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 984
    Billets dans le blog
    6
    Par défaut
    En fait le CASE est plus efficace si c'est un CASE valué et non un CASE généralisé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT ...
    FROM   ...
    WHERE  CASE @TypeTravail 
              WHEN 'Tous' THEN 1
              WHEN 'Routage' AND B1.ResourceType IN ('RO', 'RP', 'RU') THEN 1
              WHEN 'Autres' AND B1.ResourceType NOT IN ('RO', 'RP', 'RU') THEN 1
              ELSE 0
           END = 1
    À lire : https://sqlpro.developpez.com/cours/sqlaz/select/#L7


    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Membre Expert
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 939
    Par défaut
    Citation Envoyé par Sylv_62 Voir le message
    Mon code actuel est rédigé de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    AND (CASE WHEN @TypeTravail = 'Routage' THEN B1. ResourceType IN ('RO', 'RP', 'RU')
    		 ELSE WHEN  @TypeTravail = 'Autres' THEN B1. ResourceType NOT IN ('RO', 'RP', 'RU')
    		 ELSE B1.ResourceType <> '' END)
    L'expression CASE n'admet seulement une expression (valeur calculée ou pas) après THEN
    https://learn.microsoft.com/fr-fr/sq...ult_expression

    Ici l'opérateur IN ou NOT IN est une conditionnelle, pas une expression ; d'où le message d'erreur

    La réponse de SQLpro, qui tient compte du fait que seules 3 valeurs sont admises (Routage, Autres, Tous), est élégante
    Le savoir est une nourriture qui exige des efforts.

  6. #6
    Membre averti
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2024
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2024
    Messages : 47
    Par défaut
    Citation Envoyé par SQLpro Voir le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT ...
    FROM   ...
    WHERE  CASE @TypeTravail 
              WHEN 'Tous' THEN 1
              WHEN 'Routage' AND B1.ResourceType IN ('RO', 'RP', 'RU') THEN 1
              WHEN 'Autres' AND B1.ResourceType NOT IN ('RO', 'RP', 'RU') THEN 1
              ELSE 0
           END = 1
    A +
    Merci pour cette lecture

    Etrangement, votre forme du case me renvoyait une erreur (je me demande si ça n'est pas simplement dû à SQL Server qui "arrange" un peu les choses à sa sauce).
    J'ai adapté en complétant ma requête de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     AND CASE 
              WHEN @TypeTravail ='Tous' THEN 1
              WHEN @TypeTravail ='Routage' AND B1.ResourceType IN ('RO', 'RP', 'RU') THEN 1
              WHEN @TypeTravail ='Autres' AND B1.ResourceType NOT IN ('RO', 'RP', 'RU') THEN 1
              ELSE 0
           END = 1
    Avec la solution donnée par Tatayo, j'ai mis un peu de temps avant de m'apercevoir que les résultats contenaient des lignes qui auraient dû être exclues.

    Avec ce case, il semble maintenant que les résultats soient plus en phase avec l'attendu.
    Le nombre de résultats renvoyés (pour les mêmes combinaisons de paramètres) a également baissé, ce qui m'a l'air d'être un bon signe.

  7. #7
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 309
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 309
    Billets dans le blog
    17
    Par défaut
    Perso je l'aurais écrite comme ça :

    AND CASE @TypeTravail
        WHEN 'Tous' THEN TRUE
        WHEN 'Routage' THEN B1.ResourceType IN ('RO', 'RP', 'RU')
        WHEN 'Autres' THEN B1.ResourceType NOT IN ('RO', 'RP', 'RU')
        ELSE FALSE
    END
    (j'aime bien remettre des pièces)
    Un problème exposé clairement est déjà à moitié résolu
    Keep It Smart and Simple

  8. #8
    Membre Expert
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 939
    Par défaut
    Citation Envoyé par Séb. Voir le message
    (j'aime bien remettre des pièces)
    Ok pour le fun
    Mais la proposition ne fonctionne pas ; exactement pour la même raison évoquée précédement
    Le savoir est une nourriture qui exige des efforts.

  9. #9
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 537
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 537
    Billets dans le blog
    10
    Par défaut
    La plupart des SGBD émettent un message d'erreur si on utilise la syntaxe CASE ma_colonne avec un deuxième argument.

    Et bizarrement, non seulement MySQL accepte cette syntaxe, mais surtout, renvoie un résultat faux :

    Exemple :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    create table T1
          (  T1ID   integer primary key
           , T1C1   char(4) not null
           , T1C2   char(2) not null
          )
    ;
    insert into T1
           (T1ID, T1C1, T1C2)
    values (1, 'ABCD', 'AA')
         , (2, 'ABCD', 'DD')
         , (3, 'ABCD', 'AA')
         , (4, 'EFGH', 'XX')
         , (5, 'EFGH', 'DD')
         , (6, 'EFGH', 'DD')
         , (7, 'ZZZZ', 'YY')
    ;
    select T1ID
         , case when T1C1 = 'ABCD' and T1C2='DD' then 'cas 1'
                when T1C1 = 'EFGH' and T1C2='XX' then 'cas 2'
                when T1C2 = 'YY'                 then 'cas 3'
                else 'autre'
           end as CASE01
         , case T1C1
                when 'ABCD' and T1C2='DD' then 'cas 1'
                when 'EFGH' and T1C2='XX' then 'cas 2'
                when T1C2 = 'YY'          then 'cas 3'
                else 'autre' 
           end as CASE02
    from T1


    Résultat avec MySQL (Postgre, SQL server et DB2 plantent, à raison) :

    Nom : Sans titre.png
Affichages : 37
Taille : 3,8 Ko


  10. #10
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 309
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 309
    Billets dans le blog
    17
    Par défaut
    case T1C1
        when 'ABCD' and T1C2='DD' then 'cas 1'
        when 'EFGH' and T1C2='XX' then 'cas 2'
        when T1C2 = 'YY'          then 'cas 3'
        else 'autre' 
    end as CASE02
    Cette construction n'a pas de sens. Pour le 1er WHEN elle revient à faire T1C1 = ('ABCD' and T1C2='DD')

    MySQL accepte 2 constructions de CASE bien distinctes => https://dev.mysql.com/doc/refman/8.4/en/case.html

    https://modern-sql.com/feature/case
    Un problème exposé clairement est déjà à moitié résolu
    Keep It Smart and Simple

  11. #11
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 537
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 537
    Billets dans le blog
    10
    Par défaut
    Comme indiqué précédemment, le problème c'est que MySQL renvoie n'importe quoi ! Il devrait réagir comme les autres SGBD en émettant un message d'erreur bloquante.
    MySQL est le seul SGBD qui réponde à la question "Quel âge avait Rimbaud ?"

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [super requete] Dumper un model avec une clause where
    Par elievar dans le forum Langage SQL
    Réponses: 3
    Dernier message: 16/03/2005, 17h05
  2. Réponses: 7
    Dernier message: 15/03/2005, 14h44
  3. [forms] Bloc basé sur une clause from
    Par plaineR dans le forum Forms
    Réponses: 11
    Dernier message: 16/12/2004, 12h02
  4. Réponses: 3
    Dernier message: 11/03/2004, 10h58
  5. Probleme dans une clause like !
    Par adil dans le forum Langage SQL
    Réponses: 6
    Dernier message: 15/07/2003, 16h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo