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 :

JOIN et COUNT


Sujet :

Langage SQL

  1. #1
    Invité(e)
    Invité(e)
    Par défaut JOIN et COUNT
    Bonjour à tous,

    je dois adapter un petit outil qui utilise mysql pour que celui-ci fonctionne avec postgresql.
    Forcément, les requetes MySQL / PgSQL n'étant pas tout à fait les mêmes, j'ai du mal.

    J'ai 2 tables planning_user & planning_periode.

    Sous mysql, j'ai la requete suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT planning_user.*, COUNT(periode_id)
    FROM planning_user 
    LEFT JOIN planning_periode
    ON planning_user.user_id = planning_periode.user_id;
    Sous psql, j'essaie la chose suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT pu.*, count(pp.periode_id)          
    FROM planning_user pu
    LEFT JOIN planning_periode pp
    ON (pu.user_id = pp.user_id);
    Cela ne fonctionne pas, à cause du count().

    Quand je fais la commande suivante, j'ai bien un résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT pu.*, pp.periode_id
    FROM planning_user pu
    LEFT JOIN planning_periode pp
    ON (pu.user_id = pp.user_id);
    Une idée ?

    Notez que je suis un grand débutant en SQL

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 386
    Points
    18 386
    Par défaut
    Il vous manque le GROUP BY dans toutes vos requêtes.

    Evitez également les *, nommez toutes les colonnes une par une.

  3. #3
    Invité(e)
    Invité(e)
    Par défaut
    Merci pour la réponse rapide.

    Cependant, ça fonctionne pas encore.

    Voici les 2 tables :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    # select * from planning_user;
          nom       | user_id |   login   | password  | droit_planification | visible_planning 
    ----------------+---------+-----------+-----------+---------------------+------------------
     
    # select * from planning_periode;
     periode_id | projet_id | user_id | date_debut |  date_fin  | duree | notes 
    ------------+-----------+---------+------------+------------+-------+-------
    Et la nouvelle commande :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT pu.nom, pu.user_id, pu.login, pu.password,
    pu.droit_planification, pu.visible_planning, count(pp.periode_id)
    FROM planning_user pu
    LEFT JOIN planning_periode pp
    ON (pu.user_id = pp.user_id)
    GROUP BY pu.user_id ORDER BY pu.user_id;
    ERREUR: la colonne « pu.nom » doit apparaître dans la clause GROUP BY ou doit être utilisé dans une fonction d'agrégat
    LINE 1: SELECT pu.nom, pu.user_id, pu.login, pu.password,

  4. #4
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    L'erreur te dit :
    Si tu GROUP BY une colonne, tu n'auras qu'une ligne par colonne.
    Si dans le SELECT, tu demandes d'autres colonnes que celles du GROUP BY, quelle valeur va-t-on prendre ?

    Exemple :
    TableT(id, col1)
    1, 1
    1, 2
    1, 3

    => que doit renvoyer pour col1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SELECT id, col1, count(*)
    FROM TableT
    GROUP BY id
    1, 2 ou 3 ?

    Si tu veux "reporter" le count(*) sur chaque ligne de détail, ce n'est pas du tout le même principe :
    - Soit tu utilises les fonctions analytiques (non dispo sous MySQL)
    - Soit tu fais le GROUP BY, puis la jointure avec la table de départ

  5. #5
    Invité(e)
    Invité(e)
    Par défaut
    Salut,

    désolé, mais j'suis vraiment une quiche en SQL .

    Voici ce que j'ai déjà avec mysql (code récupéré, c'est pas de moi).

    1) Table planning_projet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select * from planning_user;
    +---------+---------+---------+----------+---------------------+------------------+
    | nom     | user_id | login   | password | droit_planification | visible_planning |
    +---------+---------+---------+----------+---------------------+------------------+
    | admin   | ADM     | admin   | admin    | oui                 | oui              | 
    | paul    | paul    | paul    | paul     | oui                 | oui              | 
    | remi    | rem     | remi    | remi     | oui                 | oui              | 
    +---------+---------+---------+----------+---------------------+------------------+
    1) Table planning_periode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    select * from planning_periode;
    +------------+-----------+---------+------------+------------+-------+-------+
    | periode_id | projet_id | user_id | date_debut | date_fin   | duree | notes |
    +------------+-----------+---------+------------+------------+-------+-------+
    |          1 | ABCD      | ADM     | 2010-01-11 | 2010-01-29 |  NULL | NULL  | 
    |          2 | HEE       | pau     | 2010-01-11 | 2010-03-11 |  NULL | NULL  | 
    |          3 | EFGH      | pau     | 2010-01-07 | NULL       |     7 | NULL  | 
    |          4 | EFGH      | rem     | 2010-01-07 | 2010-01-14 |  NULL | NULL  | 
    |          5 | ABCD      | rem     | 2010-01-11 | 2010-01-15 |  NULL | NULL  | 
    |          6 | ABCD      | rem     | 2010-01-25 | 2010-01-27 |  NULL | NULL  | 
    |          7 | EFGH      | pau     | 2010-01-21 | 2010-01-28 |  NULL | NULL  | 
    +------------+-----------+---------+------------+------------+-------+-------+
    3) Resultat de la requete sous mysql :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT planning_user.*, COUNT(periode_id) AS totalPeriodes
    FROM planning_user LEFT JOIN planning_periode
    ON planning_user.user_id = planning_periode.user_id
    GROUP BY planning_user.user_id
    ORDER BY user_id ASC ;
    +---------+---------+---------+----------+---------------------+------------------+---------------+
    | nom     | user_id | login   | password | droit_planification | visible_planning | totalPeriodes |
    +---------+---------+---------+----------+---------------------+------------------+---------------+
    | admin   | ADM     | admin   | admin    | oui                 | oui              |             1 | 
    | paul    | pau     | paul    | paul     | oui                 | oui              |             3 | 
    | remi    | rem     | remi    | remi     | oui                 | oui              |             3 | 
    +---------+---------+---------+----------+---------------------+------------------+---------------+
    Sous une base postgresql, ce meme genre de requête ne fonctionne pas.
    Je souhaite avoir le meme résultat que 3).

    Une ptite idée ?

    Encore merci !

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 386
    Points
    18 386
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Évitez également les *, nommez toutes les colonnes une par une.
    Je m'auto-cite, vous le lirez peut-être mieux en deux fois !

  7. #7
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour Waldar,

    j'avais bien lu, c'est juste que le code de départ avec les select * n'est pas de moi, j'ai donc remis les requetes telles quelles.


  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Points : 965
    Points
    965
    Par défaut
    Bonjour,

    Pour faire très simple, il faut que votre GROUP BY contienne chaque colonne qui ne fait pas l'objet d'une agrégation (count, sum, max...), donc toutes les colonnes de votre SELECT sauf periode_id.

  9. #9
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Ok, je reprends ce que je disais :
    Si tu GROUP BY, tu n'as qu'une ligne par groupe. Dans ce cas, prendre d'autres colonnes n'a pas vraiment de sens, vu que tu ne saurais pas quelle valeur prendre.
    Maintenant, si tu avais un modèle normalisé, tu aurais une table utilisateur, que tu joindrais avec planning utilisateurs.
    Dans un cas comme dans l'autre, user_id est à la fois ta colonne de groupement et la "clef primaire" de ton entité utilisateurs... et on pourrait dire que les colonnes du SELECT n'apparaissant pas dans le GROUP BY doivent être unique dans le groupe, et donc "sélectionnables" en quelques sortes.

    Du coup, MySQL a étendu le comportement du GROUP BY :
    http://dev.mysql.com/doc/refman/5.0/...en-fields.html
    MySQL a étendu l'utilisation de la clause GROUP BY. Vous pouvez utiliser des colonnes ou des calculs de l'expression SELECT qui n'apparaissent pas dans la clause GROUP BY

    Et pourquoi ça ne marche pas sous PosgresSQL ?
    Parce que cette extension n'est pas reconnue par la norme, et que PosgresSQL suit la norme !

    Du coup, comme je le disais plus haut, que tu fasses l'agrégation à part, puis que tu joignes ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT t.user_id, t.cnt, c.* --toutes tes colonnes en fait, mais j'ai la flemme
    FROM (SELECT a.user_id, count(b.period_id) cnt
        FROM planning_user a
            JOIN planning_periode b ON a.user_id = c.user_id
        GROUP BY a.user_id) t
        JOIN planning_user c on a.user_id = c.user_id
    Le problème majeur à mon sens de l'extension MySQL, c'est qu'ils n'imposent aucune contrainte. Donc si tu l'appliques alors que l'unicité n'est pas garantie, ton résultat n'a pas de sens, et en plus dépend du plan d'exécution...

  10. #10
    Invité(e)
    Invité(e)
    Par défaut
    Cool, merci à tous pour vos explications, c'est plus clair pour moi.

    Merci pour la remarque entre mysql & postgresql également.

    Je pense maintenant que je peux m'en sortir

  11. #11
    Invité(e)
    Invité(e)
    Par défaut
    Allez, voici la requête SQL dont j'avais finalement besoin :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT pu.nom, pu.user_id, pu.login, pu.droit_planification, pu.visible_planning, COUNT(pp.periode_id) AS totalPeriodes
    FROM planning_user pu LEFT JOIN planning_periode pp
    ON pu.user_id = pp.user_id
    GROUP by pu.nom, pu.user_id, pu.login, pu.droit_planification, pu.visible_planning
    ORDER BY user_id ASC;
    Merci encore

Discussions similaires

  1. Requete avec LEFT OUTER JOIN et COUNT
    Par ThitoO dans le forum Requêtes
    Réponses: 3
    Dernier message: 30/07/2009, 23h18
  2. COUNT et RIGHT JOIN
    Par psychomatt dans le forum Langage SQL
    Réponses: 4
    Dernier message: 29/05/2006, 15h45
  3. Besoin d'aide sur une requête (JOIN + COUNT ?)
    Par PanzerKunst dans le forum Langage SQL
    Réponses: 2
    Dernier message: 01/06/2005, 10h29
  4. multiples COUNT et JOIN
    Par Ryle dans le forum Langage SQL
    Réponses: 2
    Dernier message: 30/08/2004, 08h26
  5. count() dans *plusieurs* LEFT JOIN
    Par silver_dragoon dans le forum Langage SQL
    Réponses: 2
    Dernier message: 28/06/2004, 17h20

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