KB-106987: Calculando a diferença de valores entre registros de um Campo da tabela.

Descrição:

Possuo um campo da tabela que recebe o valor de um tag com o somatório geral de determinada variável do sistema; entretanto, preciso exibir a diferença (subtração) entre os valores dos registros desta tabela, e não seu valor acumulado. Como calcular a diferença entre os registros?

NOTA: A solução proposta neste artigo, que utiliza a função analítica LAG (Transact-SQL), aplica-se ao SQL Server 2012 e versões superiores; para as demais versões e outros bancos de dados, há outra solução alternativa, publicada ao final do artigo.

Solução:

Neste caso, podemos utilizar a função analítica LAG (Transact-SQL), que acessa os dados de uma linha anterior no mesmo conjunto de resultados. A função foi inserida no SQL Server 2012; é possível utilizá-la em uma instrução SELECT, que compara valores na linha atual com valores em uma linha anterior.

Sintaxe

LAG (scalar_expression [,offset] [,default])
       OVER ( [ partition_by_clause ] order_by_clause )

Argumentos

scalar_expression
Este é valor a ser retornado com base no deslocamento especificado. É uma expressão de qualquer tipo, que retorna um único valor (escalar). scalar_expression não pode ser uma função analítica.

offset
Este é o número de linhas atrás da linha atual de onde se obtém um valor. Caso não seja especificado, o padrão será 1. offset pode ser uma coluna, subconsulta ou outra expressão avaliada para um inteiro positivo, ou então pode ser convertida implicitamente em bigint. Entretanto, offset não pode ser um valor negativo nem uma função analítica.

default
Este é valor a ser retornado quando offset estiver além do escopo da partição. Se um valor padrão não for especificado, o valor NULL será retornado. default pode ser uma coluna, subconsulta ou outra expressão, mas não pode ser uma função analítica. Portanto, default deve ter o tipo compatível com scalar_expression.

OVER ( [ partition_by_clause ] order_by_clause )
partition_by_clause divide o conjunto de resultados produzido pela cláusula FROM em partições às quais a função é aplicada. Caso não seja especificado, então a função tratará todas as linhas do conjunto de resultados da consulta como um único grupo.

order_by_clause determina a ordem dos dados antes que a função seja aplicada. Se partition_by_clause for especificado, ela então determinará a ordem dos dados na partição. order_by_clause é obrigatória. Para obter mais informações, consulte Cláusula OVER (Transact-SQL).

Exemplo de utilização:

1. Primeiramente: criando a tabela:

CREATE TABLE Hist_1 (
E3TimeStamp datetime not null,
SE_10F03 int not null,
P1F01 int not null,
P2F01 int not null
)

2. Logo após: inserindo valores:

INSERT INTO Hist_1
(E3TimeStamp,
SE_10F03,
P1F01,
P2F01)
VALUES
('17-01-2020 15:34:00', 425, 182, 345),
('17-01-2020 15:38:00', 445, 189, 356),
('17-01-2020 15:42:00', 465, 199, 360),
('17-01-2020 15:48:00', 485, 203, 394),
('17-01-2020 15:52:00', 502, 206, 454),
('17-01-2020 15:56:00', 506, 209, 480)

3. Retornando os dados inseridos anteriormente:

SELECT * FROM Hist_1

4. Utilizando a função LAG para então obter a diferença entre os registros:

SELECT Hist_1.E3TimeStamp,
        ISNULL((Hist_1.SE_10F03 - LAG(Hist_1.SE_10F03,1) OVER (ORDER BY Hist_1.E3TimeStamp ASC)) ,0) as SE_10F03,
        ISNULL((Hist_1.P1F01 - LAG(Hist_1.P1F01,1) OVER (ORDER BY Hist_1.E3TimeStamp ASC)) ,0) as P1F01,
        ISNULL((Hist_1.P2F01 - LAG(Hist_1.P2F01,1) OVER (ORDER BY Hist_1.E3TimeStamp ASC)) ,0) as P2F01
FROM Hist_1
ORDER BY Hist_1.E3TimeStamp ASC

Outra alternativa seria utilizar a seguinte sintaxe SQL:

SELECT   E3TimeStamp
        ,[SE_10F03]
        ,[SE_10F03] - (
          SELECT TOP 1 [SE_10F03]
          FROM [Hist_1] b
          WHERE a.E3TimeStamp > b.E3TimeStamp
          ORDER BY b.E3TimeStamp DESC) as Diff
FROM [Hist_1] a


Artigos Relacionados:


Print Friendly, PDF & Email

Este artigo foi útil? Was this helpful?

Classificação média - Average rating 3 / 5. Count: 2

Deixe seu Comentário

Seu endereço de e-mail não será publicado. Campos marcados com asterisco são obrigatórios *