J'ai besoin de calculer la différence d'une colonne entre deux lignes d'un tableau. Est-il possible que je puisse le faire directement dans SQL? J'utilise Microsoft SQL Server 2008.
Je cherche quelque chose comme ça:
SELECT value - (previous.value) FROM table
Imaginons que la variable "précédente" référence la dernière ligne sélectionnée. Bien sûr, avec une sélection comme celle-là, je me retrouverai avec n-1 lignes sélectionnées dans une table avec n lignes, ce n'est pas probablement, c'est exactement ce dont j'ai besoin.
Est-ce possible d'une manière ou d'une autre?
sql
sql-server
sql-server-2008
Edwin Jarvis
la source
la source
Réponses:
SQL n'a pas de notion d'ordre intégrée, vous devez donc classer par colonne pour que cela soit significatif. Quelque chose comme ça:
Si vous savez comment ordonner les choses mais pas comment obtenir la valeur précédente étant donné la valeur actuelle (par exemple, vous voulez classer par ordre alphabétique), je ne connais pas de moyen de le faire en SQL standard, mais la plupart des implémentations SQL auront extensions pour le faire.
Voici un moyen pour le serveur SQL qui fonctionne si vous pouvez classer les lignes de sorte que chacune soit distincte:
Si vous avez besoin de rompre les liens, vous pouvez ajouter autant de colonnes que nécessaire à ORDER BY.
la source
Utilisez la fonction de décalage :
Les séquences utilisées pour les identifiants peuvent sauter des valeurs, donc Id-1 ne fonctionne pas toujours.
la source
LAG(ExpressionToSelect, NumberOfRowsToLag, DefaultValue)
. Le nombre de lignes par défaut à retarder est de 1, mais vous pouvez spécifier cela et la valeur par défaut à sélectionner lorsqu'il n'est pas possible de retarder puisque vous êtes au début de l'ensemble.Oracle, PostgreSQL, SQL Server et bien d'autres moteurs SGBDR ont des fonctions analytiques appelées
LAG
etLEAD
qui font exactement cela.Dans SQL Server avant 2012, vous devez effectuer les opérations suivantes:
, où
COL1
est la colonne par laquelle vous commandez.Avoir un index sur
(COL1, PK)
améliorera considérablement cette requête.la source
la source
JOINDRE GAUCHE la table à elle-même, avec la condition de jointure élaborée de sorte que la ligne correspondante dans la version jointe de la table soit une ligne précédente, pour votre définition particulière de "précédente".
Mise à jour: Au début, je pensais que vous voudriez conserver toutes les lignes, avec NULL pour la condition où il n'y avait pas de ligne précédente. En le relisant, vous voulez simplement que les lignes soient éliminées, vous devriez donc une jointure interne plutôt qu'une jointure gauche.
Mettre à jour:
Les versions plus récentes de Sql Server ont également les fonctions de fenêtrage LAG et LEAD qui peuvent également être utilisées pour cela.
la source
la source
La réponse sélectionnée ne fonctionnera que s'il n'y a pas de lacunes dans la séquence. Cependant, si vous utilisez un identifiant généré automatiquement, il est probable qu'il y ait des espaces dans la séquence en raison des insertions qui ont été annulées.
Cette méthode devrait fonctionner si vous avez des lacunes
la source