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

Les fonctions d'agrégation ne sont pas autorisées dans une requête récursive. Existe-t-il une autre manière d'écrire cette requête ?

Ce n'est pas joli, mais j'ai trouvé une solution :

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;

Dans la partie récursive de la requête, au lieu d'appeler GROUP BY et calculer avg(r.rank) , j'utilise une fonction window partitionnée sur les mêmes colonnes. Cela a le même effet que le calcul du classement moyen.

Un inconvénient est que ce calcul se produit plus de fois que nécessaire. Si nous pouvions GROUP BY puis avg(r.rank) , ce serait plus efficace que avg(r.rank) puis GROUP BY .

Puisqu'il y a maintenant des doublons dans le résultat de la requête imbriquée, j'utilise DISTINCT pour les filtrer, puis la requête externe calcule un RANK() de tous les athlètes dans chaque category_id sur la base de ces moyennes.

Je serais toujours désireux d'entendre si quelqu'un connaît une meilleure façon de le faire. Merci