2011-10-14 4 views
3

J'ai la requête suivante:Postgres Rang Comme colonne

SELECT name, rank() OVER (PARTITION BY user_id ORDER BY love_count DESC) AS position FROM items 

Et je voudrais maintenant faire une clause where sur le rang() fonction:

SELECT name, rank() OVER (PARTITION BY user_id ORDER BY love_count DESC) AS position FROM items WHERE position = 1 

C'est, je veux pour interroger l'élément le plus aimé pour chaque utilisateur. Cependant, il en résulte:

PGError: ERROR: column "position" does not exist

Aussi, j'utilise Rails AREL pour le faire et je voudrais permettre chaîner. C'est le code Ruby qui crée la requête:

Item.select("name, rank() OVER (PARTITION BY user_id ORDER BY love_count DESC) AS position").where("position = 1") 

Des idées?

Répondre

6

Vous devez « envelopper » dans une table dérivée:

SELECT * 
FROM (
    SELECT name, 
      rank() OVER (PARTITION BY user_id ORDER BY love_count DESC) AS position 
    FROM items 
) t 
WHERE position = 1 
5

Ma première pensée était, « Utiliser une expression de table commune », comme celui-ci non testé. Le problème que vous voyez est lié à l'ordre logique d'évaluation requis par les normes SQL. SQL doit agir comme si les alias de colonne (arguments de l'opérateur AS) n'existaient pas jusqu'à après la clause WHERE est évaluée.

+0

+1 Pour performance. Je ne sais pas exactement pourquoi, mais le CTE semble être environ 2x plus rapide que la jointure imbriquée dans la réponse acceptée. – Keyo

+0

@Keyo: Avez-vous comparé les plans d'exécution? –