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 :

Un CASE dans un WHERE [11gR2]


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut Un CASE dans un WHERE
    Bonjour,

    Lié à mon problème de MERGE, j'ai essayé ce type de requête pour voir si une mise à jour de la table par rapport à sa référence est nécessaire :
    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
    SELECT *
    FROM PLEMENAGER.TYPE_POPULATION rf
    WHERE NOT EXISTS
    (
      SELECT *
      FROM GRHUM.TYPE_POPULATION act
      WHERE act.C_TYPE_POPULATION = rf.C_TYPE_POPULATION
        AND act.LC_TYPE_POPULATION = rf.LC_TYPE_POPULATION
        AND act.LL_TYPE_POPULATION = rf.LL_TYPE_POPULATION
        AND CASE WHEN act.REF_REGLEMENTAIRE IS NULL AND rf.REF_REGLEMENTAIRE IS NULL THEN TRUE ELSE FALSE END
        AND act.TEM_FONCTIONNAIRE = rf.TEM_FONCTIONNAIRE
        AND act.TEM_ATOS = rf.TEM_ATOS
        AND act.TEM_ITARF = rf.TEM_ITARF
        AND act.TEM_ENS_SUP = rf.TEM_ENS_SUP
        AND act.TEM_ENSEIGNANT = rf.TEM_ENSEIGNANT
        AND act.TEM_2DEGRE = rf.TEM_2DEGRE
        AND act.TEM_HOSPITALIER = rf.TEM_HOSPITALIER
        AND act.TEM_BIBLIO = rf.TEM_BIBLIO
        AND act.TEM_CARRIERE = rf.TEM_CARRIERE
        AND act.D_CREATION = rf.D_CREATION
        AND act.D_MODIFICATION = rf.D_MODIFICATION
        AND act.TEM_1DEGRE = rf.TEM_1DEGRE
        AND act.TEM_VISIBLE = rf.TEM_VISIBLE
        AND CASE WHEN act.D_OUVERTURE IS NULL AND rf.D_OUVERTURE IS NULL THEN TRUE ELSE FALSE END
        AND CASE WHEN act.D_FERMETURE IS NULL AND rf.D_FERMETURE IS NULL THEN TRUE ELSE FALSE END
    );
    J'ai utilisé des case parce que je ne pouvais pas utiliser l'égalité sur les colonnes contenant des NULL (en logique SQL, NULL <> NULL).

    Mais ORacle renvoie cette erreur :
    ORA-00920: opérateur relationnel non valide
    00920. 00000 - "invalid relational operator"
    *Cause:
    *Action:
    Erreur à la ligne 11, colonne 5
    Et la ligne 11 colonne 5, c'est le début de la ligne qui suit celle contenant le premier CASE.
    J'ai essayé d'encadrer le CASE avec des parenthèses mais ça ne change rien.

    Que c'est qui ne va pas dans ma requête ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Le case bien sûr. Comme je ne vois pas bien ce que vous voulez faire peut être que vous pouvez lire ce topique sur Ask Tom.

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 132
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (...)
        AND CASE WHEN act.REF_REGLEMENTAIRE IS NULL AND rf.REF_REGLEMENTAIRE IS NULL THEN TRUE ELSE FALSE END
    (...);
    Ça ne pourrait pas simplement s'écrire ainsi, expression qui sera fausse dès que l''un des deux est non null ? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        AND act.REF_REGLEMENTAIRE IS NULL AND rf.REF_REGLEMENTAIRE IS NULL
    Sinon, si tu tiens vraiment au CASE, tu peux aussi faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        AND CASE WHEN act.REF_REGLEMENTAIRE IS NULL AND rf.REF_REGLEMENTAIRE IS NULL THEN 1 ELSE 0 END = 1
    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
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    Pas bête !
    Je ne pense jamais à ces combinaisons de logique pure pour simplifier la syntaxe.
    Merci, je vais essayer ça.

    EDIT :
    Pas tout à fait bon encore, cependant parce que si les deux colonnes sont non nulles, la ligne est retournée alors qu'elle ne devrait pas.

    EDIT 2 :
    Avec ta solution du CASE se terminant par = 1, ça ne fonctionne pas non plus. J'ai d'ailleurs du mal à comprendre la syntaxe, du coup.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    Avec ton idée de CASE = 1, j'ai fait cette requête :
    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
    SELECT *
    FROM PLEMENAGER.TYPE_POPULATION rf
    WHERE NOT EXISTS
    (
      SELECT *
      FROM GRHUM.TYPE_POPULATION act
      WHERE act.C_TYPE_POPULATION = rf.C_TYPE_POPULATION
        AND act.LC_TYPE_POPULATION = rf.LC_TYPE_POPULATION
        AND act.LL_TYPE_POPULATION = rf.LL_TYPE_POPULATION
        AND (CASE WHEN act.REF_REGLEMENTAIRE IS NULL AND rf.REF_REGLEMENTAIRE IS NULL THEN 1 ELSE 0 END) = 1
        AND act.TEM_FONCTIONNAIRE = rf.TEM_FONCTIONNAIRE
        AND act.TEM_ATOS = rf.TEM_ATOS
        AND act.TEM_ITARF = rf.TEM_ITARF
        AND act.TEM_ENS_SUP = rf.TEM_ENS_SUP
        AND act.TEM_ENSEIGNANT = rf.TEM_ENSEIGNANT
        AND act.TEM_2DEGRE = rf.TEM_2DEGRE
        AND act.TEM_HOSPITALIER = rf.TEM_HOSPITALIER
        AND act.TEM_BIBLIO = rf.TEM_BIBLIO
        AND act.TEM_CARRIERE = rf.TEM_CARRIERE
        AND act.D_CREATION = rf.D_CREATION
        AND act.D_MODIFICATION = rf.D_MODIFICATION
        AND act.TEM_1DEGRE = rf.TEM_1DEGRE
        AND act.TEM_VISIBLE = rf.TEM_VISIBLE
        AND (CASE WHEN act.D_OUVERTURE IS NULL AND rf.D_OUVERTURE IS NULL THEN 1 ELSE 0 END) = 1
        AND (CASE WHEN act.D_FERMETURE IS NULL AND rf.D_FERMETURE IS NULL THEN 1 ELSE 0 END) = 1
    )
    ORDER BY rf.C_TYPE_POPULATION;
    J'obtiens toutes les lignes de la table de référence (rf).

    Si je commente toutes les lignes du WHERE sauf la première, j'obtiens zéro ligne, ce qui est normal.

    Si je décommente ensuite toutes les lignes du WHERE sauf celles concernant des colonnes de date, j'ai toujours zéro lignes.

    Si je décommente AND act.D_CREATION = rf.D_CREATION, j'obtiens 4 lignes de résultat, dont 3 ne devraient pas apparaître car les dates sont identiques dans les deux tables !

    Et si je continue à décommenter en finissant par les CASE, je finis par avoir toutes les lignes en résultat.

    Y aurait-il un problème, chez Oracle, avec la comparaison des dates ?

    EDIT : En fait, je m'aperçois que même sans les CASE, ma requête me donne un mauvais résultat mais je ne sais pas pourquoi ! Faut-il explicitement convertir avec ces horribles TO_CHAR(TO_DATE pour avoir une comparaison juste ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  6. #6
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Le plus simple
    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
     
    Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 
     
    SQL> create table emp1 as select * from emp
      2  /
    Table created
     
    SQL> select *
      2  from emp
      3  minus
      4  select * 
      5  from emp1
      6  /
    EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
    ----- ---------- --------- ----- ----------- --------- --------- ------
     
    SQL>
    Les zones de type date chez Oracle contient toujours l'heure aussi.

  7. #7
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    Bon, je finis par arriver à un résultat semble t-il satisfaisant avec cette requête que je trouve tirée par les cheveux !
    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
    SELECT *
    FROM PLEMENAGER.TYPE_POPULATION rf
    WHERE NOT EXISTS
    (
      SELECT *
      FROM GRHUM.TYPE_POPULATION act
      WHERE act.C_TYPE_POPULATION = rf.C_TYPE_POPULATION
        AND act.LC_TYPE_POPULATION = rf.LC_TYPE_POPULATION
        AND act.LL_TYPE_POPULATION = rf.LL_TYPE_POPULATION
        AND (
            CASE 
                WHEN act.REF_REGLEMENTAIRE IS NULL AND rf.REF_REGLEMENTAIRE IS NULL THEN 1 
                WHEN act.REF_REGLEMENTAIRE = rf.REF_REGLEMENTAIRE THEN 1
                ELSE 0 
            END
        ) = 1
        AND act.TEM_FONCTIONNAIRE = rf.TEM_FONCTIONNAIRE
        AND act.TEM_ATOS = rf.TEM_ATOS
        AND act.TEM_ITARF = rf.TEM_ITARF
        AND act.TEM_ENS_SUP = rf.TEM_ENS_SUP
        AND act.TEM_ENSEIGNANT = rf.TEM_ENSEIGNANT
        AND act.TEM_2DEGRE = rf.TEM_2DEGRE
        AND act.TEM_HOSPITALIER = rf.TEM_HOSPITALIER
        AND act.TEM_BIBLIO = rf.TEM_BIBLIO
        AND act.TEM_CARRIERE = rf.TEM_CARRIERE
        AND TO_CHAR(act.D_CREATION) = TO_CHAR(rf.D_CREATION)
        AND TO_CHAR(act.D_MODIFICATION) = TO_CHAR(rf.D_MODIFICATION)
        AND act.TEM_1DEGRE = rf.TEM_1DEGRE
        AND act.TEM_VISIBLE = rf.TEM_VISIBLE
        AND 
        (
            CASE 
                WHEN act.D_OUVERTURE IS NULL AND rf.D_OUVERTURE IS NULL THEN 1 
                WHEN TO_CHAR(act.D_OUVERTURE) = TO_CHAR(rf.D_OUVERTURE) THEN 1
                ELSE 0 
            END
        ) = 1
        AND 
        (
            CASE 
                WHEN act.D_FERMETURE IS NULL AND rf.D_FERMETURE IS NULL THEN 1 
                WHEN TO_CHAR(act.D_FERMETURE) = TO_CHAR(rf.D_FERMETURE) THEN 1
                ELSE 0 
            END
        ) = 1
    )
    ORDER BY rf.C_TYPE_POPULATION
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    Je n'avais pas pensé non plus au MINUS mais il me retourne 4 lignes dont 3 qui, a priori, ne devraient pas être retournées, sous réserve de vérification plus approfondie.

    EDIT : Je confirme que trois lignes ne devraient pas être retournées.
    Dommage, c'était beaucoup plus simple !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

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

Discussions similaires

  1. CASE dans un WHERE avec un IN()
    Par seb.49 dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 12/08/2010, 12h21
  2. utilisation d'un case dans un where
    Par stephyugh dans le forum Langage SQL
    Réponses: 3
    Dernier message: 31/10/2007, 17h31
  3. un CASE dans un WHERE...
    Par nox75 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 27/09/2007, 14h47
  4. Problème de syntaxe d'un CASE dans un WHERE?
    Par Danny Blue dans le forum Langage SQL
    Réponses: 4
    Dernier message: 05/04/2007, 23h18
  5. [t-sql] instruction CASE dans clause WHERE
    Par ignitionflip dans le forum Langage SQL
    Réponses: 4
    Dernier message: 22/01/2007, 18h07

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