102 votes

Fonction SQL Row_Number() dans la clause Where

J'ai trouvé une réponse à une question avec le Row_Number() dans la clause where. Lorsque j'ai essayé une requête, j'ai obtenu l'erreur suivante :

"Msg 4108, Niveau 15, Etat 1, Ligne 1 Les fonctions fenêtrées ne peuvent apparaître que dans les clauses SELECT ou ORDER BY".

Voici la requête que j'ai essayée. Si quelqu'un sait comment résoudre ce problème, faites-le moi savoir.

SELECT employee_id 
FROM V_EMPLOYEE 
WHERE row_number() OVER ( ORDER BY employee_id ) > 0 
ORDER BY Employee_ID

103voto

Scott Ivey Points 19577

Pour contourner ce problème, intégrez votre instruction select dans un CTE, puis effectuez une requête sur ce CTE et utilisez les résultats de la fonction fenêtrée dans la clause where.

WITH MyCte AS 
(
    select   employee_id,
             RowNum = row_number() OVER ( order by employee_id )
    from     V_EMPLOYEE 
    ORDER BY Employee_ID
)
SELECT  employee_id
FROM    MyCte
WHERE   RowNum > 0

66voto

Quassnoi Points 191041
SELECT  employee_id
FROM    (
        SELECT  employee_id, ROW_NUMBER() OVER (ORDER BY employee_id) AS rn
        FROM    V_EMPLOYEE
        ) q
WHERE   rn > 0
ORDER BY
        Employee_ID

Notez que ce filtre est redondant : ROW_NUMBER() à partir de 1 et est toujours supérieure à 0 .

34voto

swa Points 81
Select * from 
(
    Select ROW_NUMBER() OVER ( order by Id) as 'Row_Number', * 
    from tbl_Contact_Us
) as tbl
Where tbl.Row_Number = 5

22voto

Matthew Jones Points 13864

Je pense que vous voulez quelque chose comme ça :

SELECT employee_id 
FROM  (SELECT employee_id, row_number() 
       OVER (order by employee_id) AS 'rownumber' 
       FROM V_EMPLOYEE) TableExpressionsMustHaveAnAliasForDumbReasons
WHERE rownumber > 0

10voto

Shannon Severance Points 8143

En réponse aux commentaires sur la réponse de rexem, en ce qui concerne la question de savoir si une vue en ligne ou un CTE serait plus rapide, j'ai remanié les requêtes pour utiliser une table que j'avais, et que tout le monde avait, à disposition : sys.objects.

WITH object_rows AS (
    SELECT object_id, 
        ROW_NUMBER() OVER ( ORDER BY object_id) RN
    FROM sys.objects)
SELECT object_id
FROM object_rows
WHERE RN > 1

SELECT object_id
FROM (SELECT object_id, 
        ROW_NUMBER() OVER ( ORDER BY object_id) RN
    FROM sys.objects) T
WHERE RN > 1

Les plans de requêtes produits étaient exactement les mêmes. Je m'attendrais à ce que, dans tous les cas, l'optimiseur de requêtes produise le même plan, au moins en remplaçant simplement le CTE par une vue en ligne ou vice versa.

Bien entendu, essayez vos propres requêtes sur votre propre système pour voir s'il y a une différence.

Aussi, row_number() dans la clause where est une erreur courante dans les réponses données sur Stack Overflow. En toute logique row_number() n'est pas disponible tant que la clause de sélection n'est pas traitée. Les gens oublient cela et lorsqu'ils répondent sans tester la réponse, celle-ci est parfois fausse. (Une accusation dont je me suis moi-même rendu coupable).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X