Pour obtenir le résultat sans sous-requête , vous devez recourir à la ruse de la fonction de fenêtre avancée :
SELECT sum(count(*)) OVER () AS tickets_count
, sum(min(a.revenue)) OVER () AS atendees_revenue
FROM tickets t
JOIN attendees a ON a.id = t.attendee_id
GROUP BY t.attendee_id
LIMIT 1;
sqlfiddle
Comment ça marche ?
La clé pour comprendre cela est la séquence des événements dans la requête :
fonctions d'agrégat -> fonctions de fenêtre -> DISTINCT -> LIMIT
Plus de détails :
- Meilleur moyen d'obtenir le nombre de résultats avant l'application de LIMIT
Pas à pas :
-
Je
GROUP BY t.attendee_id
- ce que vous feriez normalement dans une sous-requête. -
Ensuite, je fais la somme des comptes pour obtenir le nombre total de billets. Pas très efficace, mais forcé par votre exigence. La fonction d'agrégation
count(*)
est enveloppé dans la fonction de fenêtresum( ... ) OVER ()
pour arriver à l'expression pas si courante :sum(count(*)) OVER ()
.Et additionnez le revenu minimum par participant pour obtenir la somme sans doublons.
Vous pouvez également utiliser
max()
ouavg()
au lieu demin()
au même effet querevenue
est garanti d'être le même pour chaque ligne par participant.Cela pourrait être plus simple si
DISTINCT
était autorisé dans les fonctions de fenêtre, mais PostgreSQL n'a pas (encore) implémenté cette fonctionnalité. Par documentation :Les fonctions de fenêtre d'agrégation, contrairement aux fonctions d'agrégation normales, n'autorisent pas
DISTINCT
ouORDER BY
à utiliser dans la liste des arguments de la fonction. -
La dernière étape consiste à obtenir une seule ligne. Cela pourrait être fait avec
DISTINCT
(norme SQL) puisque toutes les lignes sont identiques.LIMIT 1
sera cependant plus rapide. Ou la forme standard SQLFETCH FIRST 1 ROWS ONLY
.