PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Obtenir la somme distincte d'une colonne de table jointe

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 :

  1. Je GROUP BY t.attendee_id - ce que vous feriez normalement dans une sous-requête.

  2. 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être sum( ... ) 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() ou avg() au lieu de min() au même effet que revenue 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 ou ORDER BY à utiliser dans la liste des arguments de la fonction.

  3. 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 SQL FETCH FIRST 1 ROWS ONLY .