sql >> Database >  >> RDS >> PostgreSQL

Geaggregeerde functies zijn niet toegestaan ​​in een recursieve query. Is er een alternatieve manier om deze query te schrijven?

Het is niet mooi, maar ik heb een oplossing gevonden:

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;

In het recursieve deel van de query, in plaats van GROUP BY . aan te roepen en het berekenen van avg(r.rank) , Ik gebruik een vensterfunctie gepartitioneerd op dezelfde kolommen. Dit heeft hetzelfde effect als het berekenen van de gemiddelde rangorde.

Een nadeel is dat deze berekening vaker voorkomt dan nodig is. Als we konden GROUP BY dan avg(r.rank) , dat zou efficiënter zijn dan avg(r.rank) dan GROUP BY .

Aangezien er nu duplicaten zijn in het resultaat van de geneste zoekopdracht, gebruik ik DISTINCT om deze eruit te filteren en dan berekent de buitenste query een RANK() van alle atleten in elke category_id gebaseerd op deze gemiddelden.

Ik hoor het graag als iemand een betere manier weet om dit te doen. Bedankt



  1. Kan geen gegevens in de database invoegen met optie (textarea)

  2. Voeg huidige datum in datetime-formaat in mySQL

  3. Een draaitabel maken in PostgreSQL

  4. Laravel dynamische vervolgkeuzelijst land en staat