GROUPE PAR et COMPTER de PostgreSQL
La requête:
SELECT COUNT(*) as count_all,
posts.id as post_id
FROM posts
INNER JOIN votes ON votes.post_id = posts.id
GROUP BY posts.id;
Retourne n
enregistrements dans Postgresql:
count_all | post_id
-----------+---------
1 | 6
3 | 4
3 | 5
3 | 1
1 | 9
1 | 10
(6 rows)
Je veux juste récupérer le nombre d'enregistrements retournés: 6
.
J'ai utilisé une sous-requête pour obtenir ce que je veux, mais cela ne semble pas optimum:
SELECT COUNT(*) FROM (
SELECT COUNT(*) as count_all, posts.id as post_id
FROM posts
INNER JOIN votes ON votes.post_id = posts.id
GROUP BY posts.id
) as x;
Comment puis-je obtenir le nombre d'enregistrements dans ce contexte droit dans PostgreSQL?
- Pourquoi pensez-vous qu'il n'est pas optimale?
- Cela semble comme une opération si courante il y aurait un moyen plus facile.
Vous devez vous connecter pour publier un commentaire.
Je pense que vous avez juste besoin
COUNT(DISTINCT post_id) FROM votes
.Voir "4.2.7. Les Expressions d'agrégation" section http://www.postgresql.org/docs/current/static/sql-expressions.html.
EDIT: Corrigé ma faute d'inattention par Erwin commentaire.
FROM votes
. J'ai ajouté à la forme correcte à ma réponse.Il est également
EXISTE
:Qui, dans PostgreSQL et avec plusieurs entrées sur le
n
côté comme vous avez sans doute, est généralement plus rapide quecount(DISTINCT x)
:Le plus de lignes par post il y a dans
votes
, plus la différence dans les performances. Juste essayer avecexplain analyze
.count(DISTINCT x)
permettra de recueillir toutes les lignes, de tri ou de hachage, puis de les prendre en compte uniquement la première par identique.EXISTS
ne scanvotes
(ou, de préférence, un index surpost_id
) jusqu'à la première correspondance est trouvée.Si chaque
post_
id est garanti d'être présent dans la tableposts
(par exemple, par la contrainte de clé étrangère), ce court formulaire est équivalente à la forme longue:Cela peut effectivement être plus rapide que la première requête avec
EXISTS
, avec pas ou peu d'entrées par la poste.La requête que vous avez eu des travaux dans la forme plus simple, trop:
De référence
Pour vérifier mes demandes, j'ai couru un test sur mon serveur de test avec des ressources limitées. Le tout dans un schéma distinct:
Configuration de Test
Faux typique d'un post /vote situation:
Toutes les requêtes suivantes retourné le même résultat (8093 de 9107 postes votes).
J'ai couru 4 tests avec
EXPLAIN ANALYZE
(au meilleur des cinq) sur Postgres 9.1.4 avec chacun des trois requêtes et annexé le résultant total runtimes.Comme est.
Après ..
Après ..
Après ..
count(*) ... WHERE EXISTS
count(DISTINCT x)
au long de la forme avec une jointurecount(DISTINCT x)
- forme courte sans adhérerMeilleur moment pour requête d'origine en question:
Pour version simplifiée:
@wildplasser de la requête avec une CTE utilise le même plan que la forme longue (analyse d'index sur les postes, analyse d'index sur les votes, jointure de fusion), plus un peu de surcharge pour le CCE. Meilleur temps:
Index-analyse uniquement dans les prochaines PostgreSQL 9.2 peut changer le résultat pour chacune de ces requêtes.
Liés, plus détaillée de référence pour Postgres 9.5 (en fait de la récupération des lignes distinctes, et pas seulement de comptage):
DISTINCT
dans des fonctions d'agrégation. s'avère, il n' - tout comme tous les autres principaux SGBDR. À titre de compensation (et parce que je voulais préciser que pour moi-même), j'élabore sur la performance de l'angle avec un indice de référence.À l'aide de
OVER()
etLIMIT 1
: