Vous n'êtes pas identifié(e).

#1 04/06/2014 10:18:34

[RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Bonjour,


J'ai un souci avec une requête où le LEFT JOIN ne renvoie pas toutes les lignes de la table de gauche, mais ignore les lignes renvoyant une valeur nulle. La requête utilisée utilise une fonction PostGIS sur une colonne stockant de la géométrie mais ce n'est pas bloquant pour la compréhension, le problème étant du SQL pur à mon sens. Deux tables sont appelées :


- geo : gid, insee, date, the_geom

- periode :


 gid   |    libelle     | debut   |  fin
-------+----------------+---------+----------
  1    | 2005 - 2014    | 2005    |  2014
  1    | 1995 - 2004    | 1995    |  2004
  1    | 1985 - 1994    | 1985    |  1994
  1    | 1975 - 1984    | 1975    |  1984
  1    | 1965 - 1974    | 1965    |  1974
  1    | 1945 - 1964    | 1945    |  1964
  1    | avant 1945     | 0       |  1944
SELECT
 periode.libelle AS periode,
 coalesce(sum(st_length(geo.the_geom)), 0) AS length
 
FROM periode
 LEFT JOIN geo ON geo.date BETWEEN periode.debut AND periode.fin

WHERE geo.insee = '086009'
 
GROUP BY periode.libelle, periode.gid

ORDER BY periode.gid DESC ;


Résultat de la requête : il manque la ligne « avant 1945 » car aucune date ne correspond à cette tranche dans ma table geo.


 periode        | length
----------------+-----------
 2005 - 2014    | 103
 2005 - 2014    | 56
 1985 - 1994    | 18
 1975 - 1984    | 5.7
 1965 - 1974    | 5.3
 1945 - 1964    | 0.2

Si je supprime la clause WHERE, le problème n'existe plus puisque j'ai des dates renseignées pour chaque période (je récupère bien mes 7 lignes).


Problème SQL classique je pense, mais je ne vois pas pourquoi le LEFT JOIN ne retourne pas l'ensemble des lignes...




Merci pour votre aide !


Thomas

Dernière modification par Thomas Williamson (04/06/2014 16:00:59)

Hors ligne

#2 04/06/2014 10:51:38

jpargudo
Administrateur

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Bonjour,

J'ai lu en diagonale, mais.. à tout hasard, avez-vous essayé :

  * de remplacer LEFT par RIGHT?
  * de changer le where en :  WHERE (geo.insee = '086009' or geo.insee is null)

(pas trop le temps de vous répondre plus là :-(... plus tard peut-être)

Bien à vous,

Hors ligne

#3 04/06/2014 10:59:26

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Oui bien sûr, ça donne ça (logique : la ligne vide correspond aux dates non reseignées) :


 periode        | length
----------------+-----------
                | 87
 2005 - 2014    | 103
 2005 - 2014    | 56
 1985 - 1994    | 18
 1975 - 1984    | 5.7
 1965 - 1974    | 5.3
 1945 - 1964    | 0.2

Hors ligne

#4 04/06/2014 11:00:46

jpargudo
Administrateur

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Re, voir le commentaire modifié entre temps plus haut:


  * de changer le where en :  WHERE (geo.insee = '086009' or geo.insee is null)

Hors ligne

#5 04/06/2014 11:05:47

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Je viens de tester, ça ne change rien... Je n'ai aucune ligne pour lesquelles le code insee n'est pas renseigné.

Hors ligne

#6 04/06/2014 11:08:17

jpargudo
Administrateur

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

SELECT
periode.libelle AS periode,
coalesce(sum(st_length(geo.the_geom)), 0) AS length

FROM periode
LEFT JOIN geo ON geo.date

WHERE geo.insee = '086009'
and ((geo.date BETWEEN periode.debut AND periode.fin) or (geo.date is null))

GROUP BY periode.libelle, periode.gid

ORDER BY periode.gid DESC ;


... donne quoi?

Hors ligne

#7 04/06/2014 11:14:08

jpargudo
Administrateur

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

RE,

D'ailleurs je me dis que cette jointure est bien curieuse, ... et que faire un coalesce après un  sum aussi

Voici donc ce que je vous propose:

SELECT
periode.libelle AS periode,
sum(coalesce(st_length(geo.the_geom),0)) AS length

FROM periode
LEFT JOIN geo ON geo.date = periode.date

WHERE geo.insee = '086009'
and ((geo.date BETWEEN periode.debut AND periode.fin) or (geo.date is null))

GROUP BY periode.libelle, periode.gid

ORDER BY periode.gid DESC ;


... en supposant que vos dates sont des entiers pleins genre 2014 d'un côté et 2014 de l'autre...
... si ça n'était pas le cas:

LEFT JOIN geo ON extract(year from geo.date) = periode.date


... voilà

Hors ligne

#8 04/06/2014 11:17:44

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Heu... ça marche oui et non : la ligne « avant 1945 » est bien renvoyée mais les chiffres sortis sont aberrants... Je ne dois pas mélanger les dates non renseignées puisque je travaille justement sur les dates renseignées.

Dernière modification par Thomas Williamson (04/06/2014 11:26:24)

Hors ligne

#9 04/06/2014 11:22:44

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Les dates sont des entiers pleins, mais... je n'ai pas de colonne date dans ma table periode (cf. mon premier mail). Je ne comprends pas votre réponse de 10:14.

Hors ligne

#10 04/06/2014 14:43:34

jpargudo
Administrateur

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Re,

Pouvez vous poster un exemple de données/structure de la table géo?
Sans cela j'aurai du mal à reproduire de mon côté;

Bien à vous,

Hors ligne

#11 04/06/2014 15:42:20

damalaan
Membre

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

jpargudo a écrit :

Pouvez vous poster un exemple de données/structure de la table géo?

oui ca serait plus facile!

Avez vous essayé déjà un simple select sans regroupement pour voir ce que ca renvoie?

Hors ligne

#12 04/06/2014 16:00:27

Re : [RESOLU] LEFT JOIN n'affiche pas toutes les lignes

Solution trouvée en supprimant la clause WHERE et en passant le filtre sur le code insee dans la jointure gauche directement :


SELECT
 periode.libelle AS periode,
 coalesce(sum(st_length(geo.the_geom)), 0) AS length
 
FROM periode
 LEFT JOIN geo ON geo.date BETWEEN periode.debut AND periode.fin AND geo.insee = '086009'

GROUP BY periode.libelle, periode.gid

ORDER BY periode.gid DESC ;

Thomas

Hors ligne

Pied de page des forums