sql >> Databasteknik >  >> RDS >> PostgreSQL

Aggregatfunktioner är inte tillåtna i en rekursiv fråga. Finns det något alternativt sätt att skriva den här frågan?

Det är inte snyggt, men jag hittade en lösning:

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;

I den rekursiva delen av frågan, istället för att anropa GROUP BY och beräkna avg(r.rank) , Jag använder en fönsterfunktion som är partitionerad på samma kolumner. Detta har samma effekt för att beräkna den genomsnittliga rangen.

En nackdel är att denna beräkning sker fler gånger än vad som är nödvändigt. Om vi ​​kunde GROUP BY sedan avg(r.rank) , det skulle vara mer effektivt än avg(r.rank) sedan GROUP BY .

Eftersom det nu finns dubbletter i resultatet av den kapslade frågan använder jag DISTINCT för att filtrera bort dessa och sedan beräknar den yttre frågan en RANK() av alla idrottare i varje category_id baserat på dessa medelvärden.

Jag skulle fortfarande gärna höra om någon vet om ett bättre sätt att göra detta. Tack



  1. Ansluter Microsoft Excel till Xero

  2. Tom PHP-utdata från MySQL-databas för en longblob

  3. Gruppera efter LIKE av ett kolumnvärde

  4. Komma igång med PostgreSQL 11 på Ubuntu 18.04