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 Firebird Discussion :

Pb Jointure reflexive et champ NULL


Sujet :

SQL Firebird

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 44
    Points : 35
    Points
    35
    Par défaut Pb Jointure reflexive et champ NULL
    Bonjour,

    J'ai un pb sur la requete suivante qui me permet de construire une vue:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
         SELECT L1.NO_LIGNE_BUDGET,
         L1.VALEUR,
         L1.NO_LIGNE_BUDGET_HISTO,
         L1.NO_BUDGET,
         L1.DATE_ECHEANCE,
         L1.TITRE_LIGNE_BUDGET,
         L1.DATE_CREATION,
         L1.COMMENTAIRE_HISTO,
         L1.LIB_COLLAB_CREA,
         L1.TYPE_LIGNE,
         'F'
         FROM LIGNES_BUDGET L1
         INNER JOIN LIGNES_BUDGET L2
         on (L1.no_ligne_budget) NOT IN (L2.no_ligne_budget_histo)
    La table lignes_budget possede une clé secondaire reflexive sur le champs NO_LIGNE_BUDGET_HISTO qui permet de stocker l'historique de modification des lignes de budget. Le but de la vue est de faire apparaitre pour chaque ligne si elle a été utilisée dans le cadre d'une historisation en marquant un champ à la valeur V ou F.

    Le code ci-dessus devrait donc retourner les lignes de budgets qui ne sont pas liées à une historisation.

    Le probleme est le suivant, si le champ ligne_budget_histo est à NULL pour tout les enregistrements, la requete ne retourne rien, a partir d'une moment ou une des lignes a une valeur pour ce champ, la vue est créée correctement.

    Je n'arrive pas à comprendre cette erreur au niveau de ma syntaxe SQL. Est ce que c'est un bug de Firebird (1.5.1) ou bien une mauvaise utilisation des champs à NULL???

  2. #2
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    C'est plutot étrange votre jointure.

    Utiliser un Not IN alors qu'il n'y a qu'une valeur à droite n'est pas très judicieux. Un <> serait plus juste d'un point de vue syntaxe.

    Maintenant d'un point de vue raisonnement il y a il me semble bien plus simple. Plutot que de faire un UNION de deux requetes (une qui selectionne les enregistrements ayant un historique et une seconde ceux sans historique) faire une seule requete avec une jointure gauche.

    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
    SELECT L1.NO_LIGNE_BUDGET, 
         L1.VALEUR, 
         L1.NO_LIGNE_BUDGET_HISTO, 
         L1.NO_BUDGET, 
         L1.DATE_ECHEANCE, 
         L1.TITRE_LIGNE_BUDGET, 
         L1.DATE_CREATION, 
         L1.COMMENTAIRE_HISTO, 
         L1.LIB_COLLAB_CREA, 
         L1.TYPE_LIGNE, 
         'F' as HISTORISATION 
         case when L2.no_ligne_budget_histo is null then 'F' else 'V' end as HISTORISATION
         FROM LIGNES_BUDGET L1 
         Left JOIN LIGNES_BUDGET L2 
         on (L1.no_ligne_budget = L2.no_ligne_budget_histo)
    Je ne suis pas certain d'avoir bien utilisé les bonnes colonnes pour la jointure, vu que je ne connais pas votre contrainte d'intégrité.
    Mais bon dans l'esprit c'est plutot ce genre de requete qu'il faut faire d'un point de vue performance c'est bien mieux.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 44
    Points : 35
    Points
    35
    Par défaut
    Ta requete ne me semble pas convenir. En fait lorsqu'une ligne a été "historisée" cela signifie qu'une nouvelle ligne la remplace est donc que l'ancienne est devenue obsolete. Ce n'est pas parce que le champ no_ligne_budget_histo de la ligne n°36 est à NULL que la ligne n'est pas obsolete!!! Ainsi une autre ligne de budget avoir le champ no_ligne_budget_histo=36 est ainsi rendre la ligne 36 obsolete.

    Ensuite, oui effectivement pour le NOT IN, j'avais mis <> au départ mais vu que la requete ne retournait pas qqch de juste j'ai essayait avec autre chose et j'ai pas remi ma requete telle qu'elle etait au départ

    En tout cas le principe que tu me donnes à l'air bon je teste et je vous dis ce que ca donne

  4. #4
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Citation Envoyé par VincentR
    Ta requete ne me semble pas convenir. En fait lorsqu'une ligne a été "historisée" cela signifie qu'une nouvelle ligne la remplace est donc que l'ancienne est devenue obsolete. Ce n'est pas parce que le champ no_ligne_budget_histo de la ligne n°36 est à NULL que la ligne n'est pas obsolete!!!
    Ce n'est pas ce que j'ai écrit
    Soit vous ne connaissez pas les jointures gauches soit vous n'avez pas vu que j'en avait faite une.

    Ma requete liste toutes les lignes de votre table. Puis regarde s'il y a une ligne de cette table qui aurait la colonne histo égale à son numéro de ligne.

    S'il trouve une tel correspondance toutes les valeurs des colonnes de L2 et notamment la valeur histo ne sera pas null (puisqu'il aura trouvé une valeur de jointure) s'il ne trouve pas de correspondance toutes les valeurs de L2 (et donc L2...histo) sont à null.

    Ce qui veux bien dire que quand L2.histo est à null (j'insiste sur L2) c'est qu'il n'y a pas d'historisation.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 44
    Points : 35
    Points
    35
    Par défaut
    Ca y est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT L1.NO_LIGNE_BUDGET,
         L1.VALEUR,
         L1.NO_LIGNE_BUDGET_HISTO,
         L1.NO_BUDGET,
         L1.DATE_ECHEANCE,
         L1.TITRE_LIGNE_BUDGET,
         L1.DATE_CREATION,
         L1.COMMENTAIRE_HISTO,
         L1.LIB_COLLAB_CREA,
         L1.TYPE_LIGNE,
         case when L1.no_ligne_budget NOT IN (SELECT NO_LIGNE_BUDGET_HISTO
                                             FROM LIGNES_BUDGET
                                             WHERE NO_LIGNE_BUDGET_HISTO IS NOT NULL) then 'F' else 'V' end as OBSOLETE
         FROM LIGNES_BUDGET L1;
    Si y a une autre solution qui est préférable dites moi

  6. #6
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Votre solution marchera, mais sera bien moins performante que la mienne. Plus vous aurez d'enregistrement dans votre table plus votre requete sera lente et lourde à exécuter.

    Une jointure gauche sera plus performante.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 44
    Points : 35
    Points
    35
    Par défaut
    Ok pardon j'avais pas vu le post précedant, donc oui j'ai compris, désolé ca me paraissait pas évident à voir votre démarche, mais c'est vrai que c'est efficasse

    Merci, j'opte pour votre solution alors

  8. #8
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Citation Envoyé par VincentR
    Ok pardon j'avais pas vu le post précedant, donc oui j'ai compris, désolé ca me paraissait pas évident à voir votre démarche, mais c'est vrai que c'est efficasse

    Merci, j'opte pour votre solution alors
    Vous n'avez pas à vous excuser il n'y pas de mal.
    D'autant plus que je vous ai raconté des bétises.
    A cause de (ou plutot grace à ) la mise en cache du résultat de la sous requete il se pourait que votre solution soit plus performante.
    Donc c'est a vous de regarder laquel est la plus performante des deux.

    De plus vous avez trouvé une solution ce qui est bien (C'est toujours mieux quand on trouve par soit même).
    Donc félicitation.

    Il y a aussi une autre solution (qui aura les même performances que celle que vous avez proposé) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT L1.NO_LIGNE_BUDGET, 
         L1.VALEUR, 
         L1.NO_LIGNE_BUDGET_HISTO, 
         L1.NO_BUDGET, 
         L1.DATE_ECHEANCE, 
         L1.TITRE_LIGNE_BUDGET, 
         L1.DATE_CREATION, 
         L1.COMMENTAIRE_HISTO, 
         L1.LIB_COLLAB_CREA, 
         L1.TYPE_LIGNE, 
         case when exists (SELECT NO_LIGNE_BUDGET_HISTO 
                                             FROM LIGNES_BUDGET 
                                             WHERE NO_LIGNE_BUDGET_HISTO = L1.no_ligne_budget) then 'V' else 'F' end as OBSOLETE 
         FROM LIGNES_BUDGET L1;
    Bonne continuation.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2004
    Messages : 44
    Points : 35
    Points
    35
    Par défaut
    Juste pour l'info, avec l'analyseur de performance de requetes de IBManager, j'obtient bien les meme performances avec les requetes utilisants le IN et le EXIST et celles ci sont plus efficasses que la requete utilisant la jointure :p

    Voili

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

Discussions similaires

  1. Résultat jointure avec champs null
    Par ideal23 dans le forum Langage SQL
    Réponses: 26
    Dernier message: 12/12/2011, 11h12
  2. Jointure et champs null
    Par Tevsox dans le forum Langage SQL
    Réponses: 6
    Dernier message: 26/10/2011, 09h03
  3. jointure avec champ à null
    Par radahm dans le forum PL/SQL
    Réponses: 2
    Dernier message: 03/11/2009, 10h51
  4. Requete select : jointure avec champs null
    Par Tidus159 dans le forum Langage SQL
    Réponses: 13
    Dernier message: 06/06/2008, 13h31
  5. Jointure + champ 'null'
    Par Flashball dans le forum Requêtes
    Réponses: 2
    Dernier message: 27/03/2008, 16h18

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