PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Aggregatfunktionen sind in einer rekursiven Abfrage nicht zulässig. Gibt es eine alternative Möglichkeit, diese Abfrage zu schreiben?

Es ist nicht schön, aber ich habe eine Lösung gefunden:

WITH RECURSIVE rankings(rankable_type, rankable_id, athlete, value, rank) AS (
  SELECT 'Sport', sport_id, athlete, seconds, RANK() over(PARTITION BY sport_id ORDER BY seconds)
  FROM lap_times lt

  UNION ALL

  SELECT 'Category', *, rank() OVER(PARTITION by category_id ORDER BY avg_rank) FROM (
    SELECT DISTINCT category_id, athlete, avg(r.rank) OVER (PARTITION by category_id, athlete) AS avg_rank
    FROM categories c
    JOIN memberships m ON m.category_id = c.id
    JOIN rankings r ON r.rankable_type = m.member_type AND r.rankable_id = m.member_id
  ) _
)
SELECT * FROM rankings;

Im rekursiven Teil der Abfrage, anstatt GROUP BY aufzurufen und Berechnen von avg(r.rank) , verwende ich eine Fensterfunktion, die auf denselben Spalten partitioniert ist. Dies hat den gleichen Effekt wie die Berechnung des durchschnittlichen Ranges.

Ein Nachteil ist, dass diese Berechnung öfter als nötig erfolgt. Wenn wir GROUP BY könnten dann avg(r.rank) , das wäre effizienter als avg(r.rank) dann GROUP BY .

Da es nun Duplikate im Ergebnis der verschachtelten Abfrage gibt, verwende ich DISTINCT diese herauszufiltern und dann berechnet die äußere Abfrage einen RANK() aller Athleten in jeder category_id basierend auf diesen Durchschnittswerten.

Ich würde trotzdem gerne hören, ob jemand einen besseren Weg kennt, dies zu tun. Danke