PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

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

#1 20/12/2016 19:44:52

adambase
Membre

requete SQL

Bonjour,

J'ai un problème.
Je voudrai écrire une requête qui donne le MAX d'un COUNT... Comment faire ?

Merci

Hors ligne

#2 20/12/2016 20:09:27

Marc Cousin
Membre

Re : requete SQL

Le max du count de quoi exactement ?

Quelque chose comme

SELECT max(toto) FROM (SELECT count(*) AS toto FROM titi GROUP BY tutu) AS tmp ?

Hors ligne

#3 21/12/2016 13:39:08

adambase
Membre

Re : requete SQL

Alors en fait j'ai trois tables:
une table "rencontre": avec comme attribut "type de rencontre", "id_rencontre", le reste n'est pas important, ça concerne date et heure et lieux..
une table membre avec un id_membre et pleins d'information sur les différents membres
une table RDV qui lie les deux tables. Ses attributs sont "id_membre" et "id_rencontre". Je voudrai savoir quelle rencontre a attiré le plus de membres, en classant par type. Donc en gros, pour chaque type de rencontre, quelle rencontre a rassembler le plus membres.

Je faisais un truc du genre:

SELECT type, rdv.id_rencontre, COUNT(DISTINCT id_membre)
FROM rdv, rencontre
WHERE rdv.id_rencontre=rencontre.id_rencontre
GROUP BY type, rdv.id_rencontre
HAVING MAX(COUNT);

Mais on ne peut pas mettre ensemble deux fonctions comme MAX et COUNT...

Hors ligne

#4 21/12/2016 14:49:12

Marc Cousin
Membre

Re : requete SQL

Donc utilisez la syntaxe que je vous ai donné plus haut… il faut résoudre ça avec une sous-requête.

Par ailleurs, dans la mesure du possible, évitez l'ancienne syntaxe de jointure, et préférez "JOIN", même si dans cette requête cela ne changera rien.

Hors ligne

#5 21/12/2016 14:50:44

adambase
Membre

Re : requete SQL

Très bien merci à vous

Hors ligne

#6 22/12/2016 13:36:22

adambase
Membre

Re : requete SQL

Je reviens vers vous pour vous poser une autre question:

voici la requête faite:

SELECT type, EXT.id_rencontre, MAX(compte)
FROM rdv AS EXT NATURAL JOIN rencontre AS OUT, (
         SELECT COUNT(id_membre) AS compte
         FROM rdv AS dedans
         GROUP BY dedans.id_rencontre) AS tmp
GROUP BY EXT.rencontre, type;

J'ai réussi grâce à vous à obtenir le max du COUNT. Mais maintenant il me l'afficher pour chaque id_rencontre alors que ce n'est pas valable. Je m'explique: par exemple pour l'id_rencontre n°3 j'ai 2 id_membre pour le type de rencontre 1. Maintenant j'ai l'id_rencontre n°4 j'ai 3 id_membre pour le type de rencontre 1.
Il m'affiche ceci:
id_rencontre   type    MAX
3                    1        3
4                     1        3

Je voudrai bien sur qu'il ne m'affiche que l'id rencontre n°4.

J'ai du mal à trouve le problème qui me parait si simple pourtant.
Désolé ce n'est vraiment pas dans mon habitude de demander trop de chose comme ça.

Dernière modification par adambase (22/12/2016 13:37:40)

Hors ligne

#7 22/12/2016 13:48:28

Marc Cousin
Membre

Re : requete SQL

Ça ne correspond pas trop à ce que vous cherchez.

Si on part de l'hypothèse que:

select type, id_rencontre,id_membre
from rencontre 
join rdv using (id_rencontre)

vous donne bien la liste des rencontres avec les membres associés et le type,

select type, id_rencontre,count(*) as nb_membre
from rencontre 
join rdv using (id_rencontre)
group by type,id_rencontre

Si vous voulez trouver pour chaque type l'id_rencontre ayant ramené le plus de membres:

select distinct on (type) type,id_rencontre,nb_membre
from
(select type, id_rencontre,count(*) as nb_membre
from rencontre 
join rdv using (id_rencontre)
group by type,id_rencontre) as tmp
order by type, nb_membre desc

C'est probablement un distinct on que vous cherchiez finalement (https://www.postgresql.org/docs/9.0/sta … elect.html)

Hors ligne

#8 22/12/2016 16:19:13

adambase
Membre

Re : requete SQL

c'est parfait, ça marche! merci beaucoup à vous!
Juste qu'est ce que le "desc" à la fin?
et comment marche le DISTINCT ON(type) type?
et comment il prend que les rencontres avec le plus de membres?
encore une fois merci, c'est mes dernières questions je pense et j'espère! smile

Dernière modification par adambase (22/12/2016 16:23:51)

Hors ligne

#9 22/12/2016 16:21:46

Marc Cousin
Membre

Re : requete SQL

«desc» pour trier par ordre descendant.

La requête demande de ne retenir qu'une seule ligne par type, la première ligne trouvée (le distinct on (type)). Le tri final sert à justement s'assurer que les enregistrements arrivent dans l'ordre dans lequel on veut pour que le premier soit le bon: on trie par type, et par nb_membre descendant.

Hors ligne

#10 22/12/2016 16:26:53

adambase
Membre

Re : requete SQL

ah d'accord, donc si j'ai bien compris d'abord on compte le nb de membre pour chaque rencontre, puis on les trie par ordre décroissant et on sélectionne la première ligne qui est donc la rencontre ayant attiré le plus de monde?
Mais si par exemple deux rencontres de même type ont attiré autant de membre? une ne sera pas sélectionner non?

Merci encore pour votre aide

Dernière modification par adambase (22/12/2016 16:31:37)

Hors ligne

#11 22/12/2016 16:51:11

Marc Cousin
Membre

Re : requete SQL

Oui, ça ne gère pas les ex-aequos

Hors ligne

#12 22/12/2016 16:52:43

adambase
Membre

Re : requete SQL

comment les gérer?

Hors ligne

#13 22/12/2016 17:04:20

Marc Cousin
Membre

Re : requete SQL

Ça va être beaucoup un peu plus compliqué.

Une des solutions, c'est d'utiliser des window functions (j'essayais de l'éviter, vu que vous êtes débutant et que je ne voulais pas que ça soit trop «brutal» pour un début).

Si on repart de cette requête

select type, id_rencontre,count(*) as nb_membre
from rencontre 
join rdv using (id_rencontre)
group by type,id_rencontre

Ce qu'on voudrait, c'est établir un classement des count(*)

select *, rank() over (partition by type order by nb_membre desc) as classement
from (
select type, id_rencontre,count(*) as nb_membre
from rencontre 
join rdv using (id_rencontre)
group by type,id_rencontre ) as tmp

Cette requête va nous donner la liste des type,id_rencontre,count(*), et une colonne classement qui est le rang de l'enregistrement pour un type donné, quand on trie par nb_membre décroissant. Si on a des ex-aequos, ils ont le même classement.

De là, si on ne veut que les premiers, ex-aequo:

select type,id_rencontre,nb_membre from
(
        select *, rank() over (partition by type order by nb_membre desc) as classement
        from (
        select type, id_rencontre,count(*) as nb_membre
        from rencontre 
        join rdv using (id_rencontre)
        group by type,id_rencontre ) as decompte
) as classements
where classement =1

https://www.postgresql.org/docs/current … indow.html

Dernière modification par Marc Cousin (22/12/2016 17:05:05)

Hors ligne

#14 22/12/2016 17:56:20

adambase
Membre

Re : requete SQL

En effet c'est un peu nouveau, je ne connais pas la fonction rank ni partition. Je ne les pas encore vues en cours.

Mais je comprend le principe de cette requête.

D'abord on compte les membres pour chaque rencontre, mais je ne comprend pas comment SQL sait qu'il doit compter "id_membre"...J'ai un peu de mal avec le COUNT(*) à chaque fois.

Puis on trie les rencontre par ordres de nb_membre décroissant
Ensuite on leur attribue des rangs (ça me fait penser a un test statistique non paramétriques...)
et quand le rang est égal à 1, donc la ou les première(s) valeure(s) dans le classement et vu qu'ils est décroissant ce sont les valeurs recherchées.
Pour finir on les affiche.
C'est bien ça?

Si vous pouvez m'expliquer comment marche "rank over" et "partition by", ce serait parfait smile . Si vous avez le temps bien sur, j'ai déjà bien abusé de votre temps...

Hors ligne

#15 22/12/2016 18:35:17

Marc Cousin
Membre

Re : requete SQL

Si possible, lisez la page que j'ai mise à la fin de mon post précédent pour commencer. Elle explique tout ça en détail avec des exemples.

Et exécutez la requête interne (celle que j'ai appelée «classements») pour voir ce qu'elle produit.

Hors ligne

Pied de page des forums