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

SQL Oracle Discussion :

Case dans une clause where avec plusiuers valeurs à évaluer


Sujet :

SQL Oracle

  1. #1
    Membre habitué
    Avatar de Oncle_Pete
    Profil pro
    Inscrit en
    avril 2006
    Messages
    246
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : avril 2006
    Messages : 246
    Points : 173
    Points
    173
    Par défaut Case dans une clause where avec plusiuers valeurs à évaluer
    Bonjour le forum,


    Je me bat avec une syntaxe que je n'arrive pas à trouver (peut etre cela n'est il pas possible d'ailleurs)

    Je suis dans ma clause Where et je souhaite évaluer tout un ensemble de machines en fonction d'une ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Where ...
    AND CASE
    	WHEN  :MaLigne =  'A' THEN uniteProd IN ('A1', 'A2', 'A5')
    	WHEN  :MaLigne =  'B' THEN uniteProd IN ('B2', 'B10')
    	WHEN  :MaLigne =  'C' THEN uniteProd IN ('C1', 'C2', 'C5')
    	WHEN  :MaLigne =  'G' THEN uniteProd IN ('G4', 'G45')
    	WHEN  :MaLigne =  'Toutes' THEN  uniteProd IN ('A1', 'A2', 'A5', 'B2', 'B10', 'C1', 'C2', 'C5', 'G4', 'G45')
        END
    J'ai l'erreur Missing keyword ou bien Missing right parenthese selon mes essais.

    Merci pour vos conseils

    Oncle pete
    Experience is the best teacher !!

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    août 2008
    Messages
    2 893
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : août 2008
    Messages : 2 893
    Points : 5 699
    Points
    5 699
    Par défaut
    Il faut obligatoirement comparé le CASE après le END et non dans le THEN, ce qui oblige à écrire du code moins intuitif :
    Code : 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    SQL> var Maligne varchar2(10);
    SQL> exec :Maligne := 'A';
     
    Procedure PL/SQL terminee avec succes.
     
    SQL> with t as (
    select 'A1' as uniteProd from dual union all
    select 'A2' as uniteProd from dual union all
    select 'A5' as uniteProd from dual union all
    select 'B2' as uniteProd from dual union all
    select 'B10' as uniteProd from dual union all
    select 'C1' as uniteProd from dual union all
    select 'C2' as uniteProd from dual union all
    select 'C5' as uniteProd from dual union all
    select 'G4' as uniteProd from dual union all
    select 'G45' as uniteProd from dual
    )
    select *
      from t
     where CASE WHEN :MaLigne = 'A' and uniteProd IN ('A1', 'A2', 'A5')
                then 1
                WHEN :MaLigne = 'B' and uniteProd IN ('B2', 'B10')
                then 1
                WHEN :MaLigne = 'C' and uniteProd IN ('C1', 'C2', 'C5')
                then 1
                WHEN :MaLigne = 'G' and uniteProd IN ('G4', 'G45')
                then 1
                WHEN :MaLigne = 'Toutes' and  uniteProd IN ('A1', 'A2', 'A5', 'B2', 'B10', 'C1', 'C2', 'C5', 'G4', 'G45')
                then 1
            END = 1;
     
    UNI
    ---
    A1
    A2
    A5
     
    SQL>  exec :Maligne := 'G';
     
    Procedure PL/SQL terminee avec succes.
     
    SQL> /
     
    UNI
    ---
    G4
    G45
     
    SQL> exec :Maligne := 'Toutes';
     
    Procedure PL/SQL terminee avec succes.
     
    SQL> /
     
    UNI
    ---
    A1
    A2
    A5
    B2
    B10
    C1
    C2
    C5
    G4
    G45
     
    10 ligne(s) selectionnee(s).
     
    SQL>
    Ou comme ça, peut être un peu moins bizarre :
    Code : 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    SQL> with t as (
    select 'A1' as uniteProd from dual union all
    select 'A2' as uniteProd from dual union all
    select 'A5' as uniteProd from dual union all
    select 'B2' as uniteProd from dual union all
    select 'B10' as uniteProd from dual union all
    select 'C1' as uniteProd from dual union all
    select 'C2' as uniteProd from dual union all
    select 'C5' as uniteProd from dual union all
    select 'G4' as uniteProd from dual union all
    select 'G45' as uniteProd from dual
    )
    select *
      from t
     where CASE WHEN :MaLigne = 'A' and uniteProd IN ('A1', 'A2', 'A5')
                then 'A'
                WHEN :MaLigne = 'B' and uniteProd IN ('B2', 'B10')
                then 'B'
                WHEN :MaLigne = 'C' and uniteProd IN ('C1', 'C2', 'C5')
                then 'C'
                WHEN :MaLigne = 'G' and uniteProd IN ('G4', 'G45')
                then 'G'
                WHEN :MaLigne = 'Toutes' and  uniteProd IN ('A1', 'A2', 'A5', 'B2', 'B10', 'C1', 'C2', 'C5', 'G4', 'G45')
                then 'Toutes'
            END = :MaLigne;
     
    UNI
    ---
    A1
    A2
    A5
    B2
    B10
    C1
    C2
    C5
    G4
    G45
     
    10 ligne(s) selectionnee(s).
     
    SQL> exec :Maligne := 'G';
     
    Procedure PL/SQL terminee avec succes.
     
    SQL> /
     
    UNI
    ---
    G4
    G45
     
    SQL>

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    En instance de retraite
    Inscrit en
    mai 2002
    Messages
    8 886
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : En instance de retraite
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 8 886
    Points : 29 623
    Points
    29 623
    Par défaut
    Quand on commence à mettre un CASE dans la clause WHERE, c'est qu'il y a une question de logique qui a été mal posée...
    Pourquoi ne pas écrire simplement cela ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    where   (:MaLigne = 'A' and uniteProd IN ('A1', 'A2', 'A5'))
        or  (:MaLigne = 'B' and uniteProd IN ('B2', 'B10'))
        or  (:MaLigne = 'C' and uniteProd IN ('C1', 'C2', 'C5'))
        or  (:MaLigne = 'G' and uniteProd IN ('G4', 'G45'))
        or  (:MaLigne = 'Toutes' and  uniteProd IN ('A1', 'A2', 'A5', 'B2', 'B10', 'C1', 'C2', 'C5', 'G4', 'G45'))
    ;
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  4. #4
    Membre habitué
    Avatar de Oncle_Pete
    Profil pro
    Inscrit en
    avril 2006
    Messages
    246
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : avril 2006
    Messages : 246
    Points : 173
    Points
    173
    Par défaut
    Merci al1_24 et skuatamad pour vos réponses


    Bien sur j'avais imaginé utiliser le OR, mais je me l'interdit.

    Un OR mal placé ou sans les parenthèses bien placé c'est susceptible de mettre à la ramasse un serveur.
    La personne qui assure la gestion de la DB nous a tenu des discours assez dramatique sur les conséquences possibles.

    J'ai pas cherché à le contredire. J'ai pas la culture pour ca.

    Demain j'analyse la réponse de al1_24 qui me semble compliquée (mais pourquoi pas ?).
    Merci encore

    OP
    Experience is the best teacher !!

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Consultant Teradata
    Inscrit en
    septembre 2008
    Messages
    8 217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Teradata
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2008
    Messages : 8 217
    Points : 17 139
    Points
    17 139
    Par défaut
    Citation Envoyé par Oncle_Pete Voir le message
    Un OR mal placé ou sans les parenthèses bien placé c'est susceptible de mettre à la ramasse un serveur.
    Tout comme une jointure, et pourtant je suis sûr que vous les utilisez.
    Votre interlocuteur prône un nivellement par le bas - c'est potentiellement dangereux alors on ne fait pas - au lieu d'un nivellement pas le haut - c'est potentiellement dangereux, voici ce qu'il faut comprendre pour éviter les écueils.

    Citation Envoyé par Oncle_Pete Voir le message
    Demain j'analyse la réponse de al1_24 qui me semble compliquée (mais pourquoi pas ?).
    C'est pourtant la plus logique et la plus lisible.

  6. #6
    Membre habitué
    Avatar de Oncle_Pete
    Profil pro
    Inscrit en
    avril 2006
    Messages
    246
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : avril 2006
    Messages : 246
    Points : 173
    Points
    173
    Par défaut
    Bonjour Waldar et merci pour ton support


    En parlant d'analyse, je voulais en effet parler de la solution de skuatamad. Je me suis emmelé les pinceaux (désolé).

    Je suis d'accord avec vous, une mauvaise liaison entre 2 tables est aussi capable de gros dégâts.
    La différence fondamentale que je vois est que les jointures sont indispensables pour accéder aux données de plusieurs tables.
    Pour le OR il doit etre possible de ne pas l'utiliser donc de faire autrement (de faire mieux) pour obtenir ce qu'on cherche
    Je suis dans cette option.

    Merci encore

    Oncle pete
    Experience is the best teacher !!

  7. #7
    Expert confirmé
    Profil pro
    Inscrit en
    août 2008
    Messages
    2 893
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : août 2008
    Messages : 2 893
    Points : 5 699
    Points
    5 699
    Par défaut
    Ce que vous pouvez aussi faire c'est générer la requête qui va bien en fonction du paramètre :Maligne, plutôt que gérer tous les cas dans une seule requête.

    Donc au final, si :Maligne = 'A', seul le filtre uniteProd IN ('A1', 'A2', 'A5') sera généré, la requête sera plus optimale dans le cas où certains critères sont très filtrant et d'autres très peu (index vs full scan)

  8. #8
    Membre habitué
    Avatar de Oncle_Pete
    Profil pro
    Inscrit en
    avril 2006
    Messages
    246
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : avril 2006
    Messages : 246
    Points : 173
    Points
    173
    Par défaut
    Bonjour skuatamad,

    Pas bête ! en effet. Pas exploré cette piste.
    Super j'ai de quoi me remettre dans les tests.

    Merci tous pour vos avis / aides

    Oncle Pete
    Experience is the best teacher !!

  9. #9
    Membre chevronné
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    avril 2013
    Messages
    1 750
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : avril 2013
    Messages : 1 750
    Points : 2 135
    Points
    2 135
    Par défaut
    Citation Envoyé par Oncle_Pete Voir le message
    La différence fondamentale que je vois est que les jointures sont indispensables pour accéder aux données de plusieurs tables.
    Objection : si tu fais un produit cartésien, tu accèdes aux données de plusieurs tables sans avoir fait de jointure
    Mais bon, le résultat ne sera pas forcément celui attendu
    DBA Oracle
    Rédacteur du blog : dbaoraclesql.canalblog.com

Discussions similaires

  1. Réponses: 2
    Dernier message: 03/07/2018, 17h34
  2. Utiliser un alias de colonne dans une clause Where MS SQL
    Par sir dragorn dans le forum Langage SQL
    Réponses: 11
    Dernier message: 12/10/2011, 10h31
  3. Case dans une clause where
    Par Blaede dans le forum Langage SQL
    Réponses: 9
    Dernier message: 10/08/2009, 17h09
  4. fonction booleenne dans une clause where ?
    Par user_h dans le forum Oracle
    Réponses: 1
    Dernier message: 20/10/2005, 16h05

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