web-dev-qa-db-fra.com

Numérotation des lignes dans PostgreSQL

Comment obtenir le numéro de ligne dans PostgreSQL lorsque les résultats sont classés par colonne?

par exemple.

SELECT 30+row_number() AS position, * 
FROM users 
ORDER BY salary DESC 
LIMIT 30 
OFFSET 30

J'ai supposé que la requête retournerait une liste comme celle-ci:

position | name | salary
31       | Joy  | 4500
32       | Katie| 4000
33       | Frank| 3500

En fait, je dois dupliquer la clause ORDER dans la requête pour la rendre fonctionnelle:

SELECT 30+row_number(ORDER BY salary DESC) AS position, * 
FROM users 
ORDER BY salary DESC 
LIMIT 30 
OFFSET 30

Existe-t-il un autre moyen de renvoyer les résultats ordonnés et numérotés sans avoir à dupliquer le code?

Je sais que cela peut être résolu en incrémentant une variable dans l'application elle-même, mais je veux le faire au niveau de la couche de base de données et revenir à l'application des résultats déjà numérotés ...

27
Radek Simko

non - le order by dans la fonction de fenêtrage et la clause order by de l'instruction select sont fonctionnellement deux choses différentes.

De plus, votre instruction produit: ERROR: window function call requires an OVER clause, Donc:

SELECT 30+row_number(ORDER BY salary DESC) AS position, * FROM users ORDER BY salary DESC LIMIT 30 OFFSET 30

devrait être:

SELECT 30+row_number() OVER(ORDER BY salary DESC) AS position, * FROM users ORDER BY salary DESC LIMIT 30 OFFSET 30

Notez que si les salaires ne sont pas uniques, rien ne garantit qu'ils produiront même la même commande. Il serait peut-être préférable de faire:

SELECT * 
FROM ( SELECT 30+row_number() OVER(ORDER BY salary DESC) AS position, * 
       FROM users )
ORDER BY position LIMIT 30 OFFSET 30

Notez également que si vous exécutez cette requête plusieurs fois avec différents décalages, vous devez:

  1. définissez votre niveau d'isolement sur sérialisable
  2. assurez-vous que tout ce que vous commandez est unique

ou vous pouvez obtenir des doublons et des lignes manquantes. Voir les commentaires sur cette réponse pour savoir pourquoi.

37
user533832