Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

LAST_VALUE dans SQL Server 2012 renvoie des résultats étranges

SQL Server ne connaît pas ou ne se soucie pas de l'ordre dans lequel les lignes ont été insérées dans la table. Si vous avez besoin d'une commande spécifique, utilisez toujours ORDER BY . Dans votre exemple ORDER BY est ambigu, sauf si vous incluez PK dans le ORDER BY . De plus, LAST_VALUE La fonction peut renvoyer des résultats impairs si vous ne faites pas attention - voir ci-dessous.

Vous pouvez obtenir le résultat attendu en utilisant MAX ou LAST_VALUE (SQLFiddle ). Ils sont équivalents dans ce cas :

SELECT
    PK, Id1, Id2
    ,MAX(PK) OVER (PARTITION BY Id1, Id2) AS MaxValue
    ,LAST_VALUE(PK) OVER (PARTITION BY Id1, Id2 ORDER BY PK rows between unbounded preceding and unbounded following) AS LastValue
FROM
    Data
ORDER BY id1, id2, PK

Le résultat de cette requête sera le même quel que soit l'ordre dans lequel les lignes ont été initialement insérées dans la table. Vous pouvez essayer de mettre INSERT déclarations dans un ordre différent dans le violon. Cela n'affecte pas le résultat.

En outre, LAST_VALUE ne se comporte pas tout à fait comme vous l'attendriez intuitivement avec la fenêtre par défaut (quand vous avez juste ORDER BY dans le OVER clause). La fenêtre par défaut est ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW , alors que vous vous attendiez à ce qu'il soit ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING . Voici une réponse SO avec un bonne explication . Le lien vers cette réponse SO se trouve sur la page MSDN pour LAST_VALUE . Ainsi, une fois que la fenêtre de ligne est spécifiée explicitement dans la requête, elle renvoie ce qui est nécessaire.

Si vous voulez connaître l'ordre dans lequel les lignes ont été insérées dans le tableau, je pense que le moyen le plus simple est d'utiliser IDENTITY . Ainsi, la définition de votre table changerait en ceci :

CREATE TABLE Data 
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)

Lorsque vous INSERT dans ce tableau, vous n'avez pas besoin de spécifier la valeur de PK , le serveur le générerait automatiquement. Il garantit que les valeurs générées sont uniques et croissantes (avec un paramètre d'incrément positif), même si de nombreux clients s'insèrent simultanément dans la table. Il peut y avoir des écarts entre les valeurs générées, mais l'ordre relatif des valeurs générées vous indiquera quelle ligne a été insérée après quelle ligne.