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

PostgreSQL Discussion :

Requête imbriquée avec deux "rangements par ordre de"


Sujet :

PostgreSQL

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Requête imbriquée avec deux "rangements par ordre de"
    Bonjour,

    Depuis plusieurs jours, j'essaie de trouver une solution simple, c'est -à-dire en une seule requête, à un problème de order by ou group by ou autres. Prenons un exemple pour expliquer ce que je recherche. Au départ, nous avons une table avec 2 champs : date et user. Comment ranger par ordre décroissant de date, puis pour chaque par ordre alphabétique des user.

    Table de départ :
    2010-01-01 | Michel
    2010-01-04 | Michel
    2010-01-04 | Michel
    2010-01-02 | Michel
    2010-01-04 | Vincent
    2010-01-04 | Vincent
    2010-01-02 | Suzanne
    2010-01-03 | Suzanne
    2010-01-03 | Bertrand
    2010-01-04 | Bertrand

    Résultat attendu :
    2010-01-04 | Bertrand
    2010-01-03 | Bertrand
    2010-01-04 | Michel
    2010-01-04 | Michel
    2010-01-02 | Michel
    2010-01-01 | Michel
    2010-01-04 | Vincent
    2010-01-04 | Vincent
    2010-01-03 | Suzanne
    2010-01-02 | Suzanne

    En gros rangement par ordre décroissant de date, puis pour chaque date quand on rencontre un user on affiche tous les enregistrements de ce user par ordre décroissant de date...
    Facile, hein !!!

    En tout cas, merci pour votre aide.

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Merci vmolines pour votre réponse, mais cela ne correspond pas à ce que je recherche.
    En effet en reprenant la table de départ en faisant un double order by, j'obtiendrai :
    2010-01-04 | Bertrand
    2010-01-04 | Michel
    2010-01-04 | Michel
    2010-01-04 | Vincent
    2010-01-04 | Vincent
    2010-01-03 | Bertrand
    2010-01-03 | Suzanne
    2010-01-02 | Michel
    2010-01-02 | Suzanne
    2010-01-01 | Michel

    Alors que le résultat attendu est :
    2010-01-04 | Bertrand
    2010-01-03 | Bertrand
    2010-01-04 | Michel
    2010-01-04 | Michel
    2010-01-02 | Michel
    2010-01-01 | Michel
    2010-01-04 | Vincent
    2010-01-04 | Vincent
    2010-01-03 | Suzanne
    2010-01-02 | Suzanne

    A nouveau merci quand même...

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ... ORDER BY Nom, Date DESC
    Non ?

    Et attention DATE est un mot clé SQL donc à éviter pour nommer des objets de la base de données.

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Non, toujours pas.
    Je ne pense pas qu'un simple order by soit la réponse. Cela doit certainement passer par une requête imbriquée.

    Pour info, sous PostGreSQL, date n'est pas un mot réservé et heureusement...

    A nouveau merci de ton aide.

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Regarde du côté de ROW_NUMBER ou autres fonctions de fenêtrage.
    L'idée qui me vient à l'esprit étant de classer les dates distinctes et de leur affecter un ROWNUM dans une sous requête puis de faire une jointure sur la date et d'utiliser ce ROWNUM pour l'ordre.

    Pas le temps de creuser davantage.

    Mais j'ai l'impression que tu cherches à afficher les données d'une certaine manière, ce qui est plutôt le boulot du programme utilisateur que du SGBD. Cela s'appelle de la cosmétique.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  7. #7
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    CinePhil, je vais regarder cela de plus près.
    Si je trouve quelque chose, je vous tiens au courant.

    Pour votre question, l'intérêt de cette requête est un gain de temps. Cela évite de faire 2 requêtes ou de faire une requête globale puis un traitement avec un langage (PHP ou autres).

    En tout cas, merci pour le conseil.

  8. #8
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par reivinternet Voir le message
    Cela évite de faire 2 requêtes ou de faire une requête globale puis un traitement avec un langage (PHP ou autres).
    Il n'est pas toujours évident qu'une requête + un traitement dans le programme soit plus long qu'une requête complexe. Lire l'article de SQLPro sur la cosmétique, je crois qu'il en parle.

    Et sur de petits volumes de données, la différence n'est pas sensible.

    Le rôle du SGBD, c'est de cracher les données selon les critères de recherche qu'on lui demande. La présentation des données, c'est le boulot du programme.

    À la limite, ORDER BY pourrait ne pas exister en SQL !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  9. #9
    Membre émérite
    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
    Points : 2 890
    Points
    2 890
    Par défaut
    Il faut découper le problème en 2: d'abord trouver l'ordre d'affichage de chaque nom, et ensuite afficher toute la table avec cet ordre là en primaire, et la date en ordre secondaire
    Pour exprimer la chose en sql, disons que la table s'appelle t et les colonnes u pour user et d pour date.

    L'ordre d'affichage de chaque nom est donné par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select u, rank() over (order by max(d) desc, u asc) AS o FROM t GROUP BY u
    Ensuite il faut joindre avec la table et ordonner avec le rang calculé au-dessus, ce qui donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    select l.u,d FROM t,
    (select u, max(d), rank() over (order by max(d) desc, u asc) AS o FROM t GROUP BY u) AS l
    WHERE l.u=t.u ORDER BY o, l.u, d desc;
    A noter qu'il faut postgres 8.4 minimum pour avoir la fonctionnalité de fenêtrage.

  10. #10
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    LE spécialiste es Postgresql estofilo a su traduire en SQL la vague idée que j'avais eue, sauf qu'il fallait donner un rank à l'utilisateur et pas à la date.

    Un petit bémol sur ta requête estofilo : les jointures utilisent depuis 1992 l'opérateur JOIN !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT l.u,d FROM t
    INNER JOIN
    (
        SELECT u, max(d), 
            rank() over (ORDER BY max(d) DESC, u ASC) AS o 
        FROM t 
        GROUP BY u
    ) AS l ON l.u=t.u 
    ORDER BY o, l.u, d DESC;
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  11. #11
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Je m'incline devant une telle requête
    Il y a un certain nombre d'éléments que je ne comprends pas, le "rank over" et le "as l on l.u=t.u", mais cela est secondaire, car le problème principal est que PostgreSQL renvoit une erreur de syntaxe :
    ERROR: syntax error at or near "over"
    inner join (select u, max(d), rank() over (orde...
    Pour info, je suis sur postgresql 8.3.8

  12. #12
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Je ne me prononcerai pas sur la partie rank, cause semble t-il de l'erreur car je ne l'ai jamais utilisée.

    Citation Envoyé par reivinternet Voir le message
    Il y a un certain nombre d'éléments que je ne comprends pas, (...) et le "as l on l.u=t.u",
    AS l : on affecte un alias à la sous-requête pour la considérer comme une pseudo table sur laquelle on peut faire une jointure.
    ON l.u = t.u : C'est la condition de la jointure.

    Une jointure s'écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM une_table
    [INNER] [LEFT] [RIGHT] [OUTER] JOIN une_autre_table ON condition_de_jointure
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  13. #13
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Ok.

    Merci pour votre aide.
    Je vais à nouveau regarder cela de plus près...

  14. #14
    Membre émérite
    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
    Points : 2 890
    Points
    2 890
    Par défaut
    rank() OVER() est une fonction de fenêtrage et n'est supporté par postgresql qu'à partir de la 8.4

    En l'absence de fenêtrage, il y a bien une solution laide qui consiste à utiliser une séquence pour générer l'ordonnancement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    CREATE TEMPORARY SEQUENCE s;
     
    SELECT l.u,d FROM t
    INNER JOIN
    (
      SELECT nextval('s') AS o, u, md FROM (
        SELECT u, max(d) AS md
        FROM t 
        GROUP BY u
        ORDER BY 2 desc, 1 asc) AS l2
    ) AS l ON l.u=t.u 
    ORDER BY o, l.u, d DESC;
    la séquence n'ayant pas besoin d'être réinitialisée à chaque appel de la requête.

  15. #15
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    salut

    sinon, sans sequence :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT dte, test2.nom
    FROM test
    INNER JOIN (
    	SELECT nom, max(dte)
    	FROM test
    	GROUP BY nom
    ) as t2(nom, maxdte) ON test.nom = t2.nom
    ORDER BY t2.maxdte DESC, test.nom, test.dte DESC

  16. #16
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    aieeeuuuuu, il doit y avoir une erreur sur les jointures car cela ne passe pas.
    Merci en tout cas.

    Je continue de regarder et vous tiens au courant.

  17. #17
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    cela ne passe pas.
    En quoi cela ne passe pas ?
    Message d'erreur ?
    Pas le bon résultat ?

    Essaie comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT dte, test2.nom
    FROM test
    INNER JOIN (
        SELECT nom, max(dte) AS maxdte
        FROM test
        GROUP BY nom
    ) AS t2 ON test.nom = t2.nom
    ORDER BY t2.maxdte DESC, test.nom, test.dte DESC
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  18. #18
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Avec l'alias, cela passe très bien.

    Merci sincèrement à tous de votre aide.




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

Discussions similaires

  1. Réponses: 4
    Dernier message: 23/10/2007, 22h09
  2. [SQL] Requête SQL avec 3 tables liées par la même relation
    Par lenstoi dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 28/08/2007, 23h32
  3. Requête SELECT avec deux champs dans une colonne ??
    Par fredhali2000 dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 08/06/2006, 10h41
  4. [MySQL] Erreur SQL 1064 : Requête imbriquée avec jointure !
    Par patchankito dans le forum Langage SQL
    Réponses: 5
    Dernier message: 31/01/2006, 10h37
  5. [DB2] Requête imbriquée avec opérateur IN
    Par JFDelges dans le forum Langage SQL
    Réponses: 23
    Dernier message: 21/12/2005, 11h27

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