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 :

WHERE et jointure externe


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    869
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 869
    Par défaut WHERE et jointure externe
    bonjour,

    si j'utilise le code suivant, la requete fonctionne bien, et la jointure externe est bien respectée: les champs 'res.nom' qui n'ont pas de correspondance dans la table 'plnj' sont bien reportés dans le resultat de la requête.( avec null pour le champ heures)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    select res.nom,sum((plnj.endtime - plnj.starttime)*24) as heures from res
    left outer join plnj on plnj.res_id=res.res_id
    group by res.nom
    par contre si j'ajoute une clause where avec un encadrement temps:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    select res.nom,sum((plnj.endtime - plnj.starttime)*24) as heures from res
    left outer join plnj on plnj.res_id=res.res_id
    where plnj.starttime between '06/01/2010' and '10/30/2010'
    group by res.nom
    La requete m'indique seulement les correspondances entre les tables.
    la jointure externe gauche ne fonctionne pas.

    Il y a un truc que je ne comprends pas ?
    est ce que cela vient de l'agregat 'SUM' qui annule la jointure externe avec une clause 'where' ?

    merci

  2. #2
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Quand la restriction (WHERE) concerne la table de droite, il faut mettre cette restriction dans la condition de jointure.

    Quand il n'y a pas de correspondance dans la table plnj, le starttime de cette table est mis à NULL comme toutes les autres colonnes de la table. Comme la condition de restriction demande que starttime soit compris entre deux valeurs, il exclut de fait les lignes où starttime est mis à NULL, donc toutes les lignes de res n'ayant pas de correspondance dans plnj.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT res.nom, sum((plnj.endtime - plnj.starttime)*24) AS heures 
    FROM res
    LEFT OUTER JOIN plnj ON plnj.res_id=res.res_id
      AND plnj.starttime BETWEEN '06/01/2010' AND '10/30/2010'
    GROUP BY res.nom
    Au fait, en SQL normalisé, les dates sont enregistrées sous la forme 'aaaa-mm-jj'. Votre BETWEEN devrait donc être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BETWEEN '2010-06-01' AND '2010-10-30'
    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 !

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Au fait, en SQL normalisé, les dates sont enregistrées sous la forme 'aaaa-mm-jj'. Votre BETWEEN devrait donc être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BETWEEN '2010-06-01' AND '2010-10-30'
    Nnnnnnnoooooonnnnnnnn.

    Le SQL étant un langage avec typage fort, on compare des dates avec des dates.

    On force la conversion de la chaîne de caractère en date, c'est la seule assurance que la requête fonctionne bien partout.

    Les conversions implicites, c'est la porte ouverte aux erreurs et au effets de bord lors de migration quelconque (os, version middleware, version sgbd, version langage de programmation...).

  4. #4
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Extrait de l'article de SQLPro sur le temps, sa mesure et ses calculs :
    La norme SQL 2 impose en outre la représentation des dates et heures suivant le masque :
    - HEURE => hh:mm:ss.nnn
    - DATE => AAAA-MM-JJ
    - DATE et HEURE => AAAA-MM-JJ hh:mm:ss.nnn
    Si la colonne starttime est, comme il se devrait de type DATE ou DATETIME, il y a de fortes chances que mon BETWEEN fonctionne. Celui de looping par contre fera une comparaison de chaînes de caractères par ordre alphabétique et la "date" 12/01/2010 sera ignorée alors qu'elle devrait être retenue.

    Comme par ailleurs les fonctions de conversion de chaîne de caractères en date dépendent parfois du SGBD utilisé, pas sûr que la solution normalisée fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE CAST(dtvaleur AS DATE) BETWEEN '2009-06-01' AND '2009-07-01'
    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
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Ce que je veux dire c'est qu'avec starttime la requête suivante sera toujours juste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    starttime BETWEEN cast('2009-06-01' as date) AND cast('2009-07-01' as date)
    Celle-ci sera parfois juste, parfois fausse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    starttime BETWEEN '2009-06-01' AND '2009-07-01'
    Comment être sûr que le SGBD converti les littéraux de droite en date et pas la colonne en littéral ? Aucun moyen.

    Le seul moyen de lever ces incertitudes est de comparer des dates avec des dates.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    869
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 869
    Par défaut précision
    bonjour,

    merci pour la réponse
    Maintenant la requete fonctionne correctement

    J'ai pas mal de lacune, vu que j'ai appris tout seul.
    Grace aux "pros" qu'il y a sur ce forum , on progresse vite .

    Petite précision concernant la discussion sur les dates:
    le champ starttime est du type datetime est le moteur est firebird 2.0

    A+

Discussions similaires

  1. Problème jointure externe et restriction where
    Par Cyrus59 dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 10/09/2012, 17h45
  2. Jointure externe avec clause WHERE
    Par ben53 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 17/03/2008, 08h56
  3. jointure externe avec un where, me pose problème!
    Par Danae dans le forum Langage SQL
    Réponses: 3
    Dernier message: 18/07/2005, 17h37
  4. [Requete] jointure externe -> where
    Par MrDuChnok dans le forum Langage SQL
    Réponses: 12
    Dernier message: 12/07/2004, 15h48
  5. [Interbase] [Triggers] jointure externe
    Par AnestheziE dans le forum InterBase
    Réponses: 9
    Dernier message: 17/11/2003, 16h17

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