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

Requêtes PostgreSQL Discussion :

Group By et relation d'unicité


Sujet :

Requêtes PostgreSQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 66
    Par défaut Group By et relation d'unicité
    Bonsoir à tous,

    Je bute sur un problème qui me parait pourtant très simple mais rien à faire
    Mes recherches se sont montrées totalement infructueuses.

    Prenons un exemple fictif :

    Une table composée de quatre colonnes :
    id (cle primaire)
    date (timestamp)
    user_id (fk)
    value (double)

    Une relation d'unicité est définie entre les clés date et user_id, car à une meme date un utilisateur ne peut pas enregistrer deux valeurs.

    Mon but est de récupérer la dernière valeur enregistrée pour chaque utilisateur. J'entends par dernière valeur enregistrée, celle qui maximise la colonne date, et non pas le plus gros id (rien n'est enregistré dans l'ordre chronologique).

    Pour cela je pensais faire une requete du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT user_id, max(date), value
    FROM table
    GROUP BY user_id;
    Le problème c'est que postgresql ne semble pas tenir compte de l'unicité déclarée entre user_id et date, donc il rale sur le fait que value n'est pas dans le GROUP BY.

    La requete suivante passe à merveille :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT user_id, max(date)
    FROM table
    GROUP BY user_id;
    Mais elle ne renvoie pas la valeur qui correspond à user_id et max(date).

    Je ne comprends pas pourquoi, alors que le couple user_id et max(date) forme une clé unique qui me retourne à coup sur la valeur, je suis incapable en une seule requête de récupérer la valeur en question. J'ai tendance à accuser pgsql de ne pas comprendre que l'unicité entre le champ date et le champ user_id lui permet de récupérer le champ value sans ambiguité, mais je procède surement de la mauvaise façon.

    J'ai tenté des trucs a base de subqueries, sans grand résultats.

    Avez vous une idée du problème ? Et si c'est connu (ce que je n'ai pas reussi a mettre en évidence avec mes recherches), comment contourner ?

    Je sèche complètement

    Merci et bonne fin de journée,

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    C'est en effet très simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT user_id,date,value FROM table
    WHERE (user_id,date) IN (
     SELECT user_id, max(date) 
     FROM TABLE 
     GROUP BY user_id);

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 66
    Par défaut
    Merci pour cette réponse.

    Je ne connaissais pas le IN couplé à la subquerie, c'est très malin ! J'avais essayé avec des where, mais on ne peut retourner qu'une valeur à la fois.

    Par contre je trouve cela très peu élégant, en fait surtout parceque mon cas réel est beeeaaaaauuucoup plus alambiqué que le simple cas que je présente, il y a des joins un peu partout, les conditions de jointures sont compliquées, etc. J'ai un peu le sentiment de taper deux fois la requete pour un résultat qui me parait tellement facile a récupérer ... si le moteur de bdd se rendait compte que dans le group by il n'a pas besoin de spécifier le champ value puisque la clause d'unicité lui interdit d'en avoir plusieurs !

    Dans tous les cas, merci, maintenant au moins je récupère le résultat sans passer par le niveau applicatif. Si par contre quelqu'un sait pourquoi la clause d'unicité n'est pas explorée lors d'un group by qu'il n'hésite pas à me le dire, ou à m'expliquer ou je me trompe dans mon raisonnement.

    Bonne soirée,

    Guiz

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    La contrainte d'unicité fait que le SGBD sait qu'à un couple (id,date) correspond une seule ligne de la table, mais pas que la même propriété est vraie pour un couple résultant d'un calcul: (id,max(date)).

  5. #5
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 954
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 954
    Par défaut
    si le moteur de bdd se rendait compte que dans le group by il n'a pas besoin de spécifier le champ value puisque la clause d'unicité lui interdit d'en avoir plusieurs !
    C'est purement sémentique, toutes colonnes présentent dans le SELECT et non agrégées doient apparaître dans la clause GROUP BY.
    MySql est laxiste sur ce point (mais pas seulement pour des colonnes uniques) et peut être d'autre SGBD "à 2 balles", mais là dessus PostgreSQL est très normatif et renvoie une erreur indépendamment de la clause unique.
    J'ai un peu le sentiment de taper deux fois la requete pour un résultat qui me parait tellement facile a récupérer
    Sans connaître la requête en question (ni la version de PG) difficile d'apporter une réponse précise mais regarde peut être du côté des CTE, pour factoriser certaines sous requêtes.

    Si tu as une version récente de PostgreSQL, les fonctions analytiques (ou de fenêtrage) permette d'éviter les utilisations massives de GROUP BY + sous requête

    Par exemple ta requête de base pourraît s'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT user_id,value, 
           max(date) over (partiton by user_id) as max_dt
      FROM TABLE

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 010
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par skuatamad Voir le message

    Par exemple ta requête de base pourraît s'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT user_id,value, 
           max(date) over (partiton by user_id) as max_dt
      FROM TABLE
    pas bon, il faudrait écrire par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    WITH 
    T AS (SELECT user_id, value, date 
                 max(date) over (partiton by user_id) as max_date
          FROM TABLE)
    SELECT user_id, value
    FROM   T 
    WHERE  date = max_date
    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 66
    Par défaut
    Citation Envoyé par estofilo Voir le message
    La contrainte d'unicité fait que le SGBD sait qu'à un couple (id,date) correspond une seule ligne de la table, mais pas que la même propriété est vraie pour un couple résultant d'un calcul: (id,max(date)).
    MAX ne modifie en rien la valeur, le rang retourné est bien un rang existant et le SGBD est en mesure de le savoir (pour cette fonction, AVG aurait été un cas différent !)

    Citation Envoyé par skuatamad
    C'est purement sémentique, toutes colonnes présentent dans le SELECT et non agrégées doient apparaître dans la clause GROUP BY.
    MySql est laxiste sur ce point (mais pas seulement pour des colonnes uniques) et peut être d'autre SGBD "à 2 balles", mais là dessus PostgreSQL est très normatif et renvoie une erreur indépendamment de la clause unique.
    Je trouve cela fort dommage ! C'est un peu ce que j'avais compris des discussions que j'ai glanées ça et là mais je n'ai jamais eu de confirmation si claire. Un jour viendra ou les SGBD seront encore plus intelligents

    Merci pour les fonctions analytiques, je ne connaissais pas du tout ce concept, je vais pouvoir approfondir ce point et surement réaliser ce que je veux.

    Bonne soirée et merci encore a vous deux !

    [edit :] et pour les CTE j'ai déjà regardé (sans savoir que ca s'appelait des CTE ) et je n'ai pas trouvé mon bonheur.

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

Discussions similaires

  1. problème relation mld groupe, evenement, publication
    Par developpeur91 dans le forum Merise
    Réponses: 1
    Dernier message: 25/03/2014, 10h41
  2. Relation reflexive et unicité
    Par izulah dans le forum Requêtes
    Réponses: 1
    Dernier message: 27/07/2011, 19h21
  3. relation n-n ,rechercher un element appartement à deux groupes
    Par Sysko le prospecteur dans le forum Langage SQL
    Réponses: 2
    Dernier message: 16/03/2009, 12h46
  4. [MCD]Relation Utilisateurs - Groupes - Fonction
    Par clarence dans le forum Schéma
    Réponses: 7
    Dernier message: 07/06/2006, 13h52

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