Preciso calcular a diferença de uma coluna entre duas linhas de uma tabela. Existe alguma maneira de fazer isso diretamente no SQL? Estou usando o Microsoft SQL Server 2008.
Estou procurando algo assim:
SELECT value - (previous.value) FROM table
Imaginando que a variável "anterior" referencia a última linha selecionada. É claro que com um select como esse vou acabar com n-1 linhas selecionadas em uma tabela com n linhas, isso não é provável, na verdade é exatamente o que preciso.
Isso é possível de alguma forma?
sql
sql-server
sql-server-2008
Edwin Jarvis
fonte
fonte
Respostas:
O SQL não tem uma noção de ordem embutida, então você precisa ordenar por alguma coluna para que isso seja significativo. Algo assim:
Se você sabe como ordenar as coisas, mas não como obter o valor anterior dado o atual (por exemplo, você quer ordenar alfabeticamente), então não conheço uma maneira de fazer isso no SQL padrão, mas a maioria das implementações de SQL terá extensões para fazer isso.
Esta é uma maneira de o servidor SQL funcionar se você puder ordenar as linhas de forma que cada uma seja distinta:
Se você precisar quebrar empate, você pode adicionar quantas colunas forem necessárias ao ORDER BY.
fonte
Use a função lag :
As sequências usadas para Ids podem ignorar valores, portanto, Id-1 nem sempre funciona.
fonte
LAG(ExpressionToSelect, NumberOfRowsToLag, DefaultValue)
. O número padrão de linhas para atrasar é 1, mas você pode especificar isso e o valor padrão para selecionar quando não for possível atrasar, pois você está no início do conjunto.Oracle, PostgreSQL, SQL Server e muitos outros motores RDBMS têm funções analíticas chamadas
LAG
eLEAD
que fazem exatamente isso.No SQL Server antes de 2012, você precisaria fazer o seguinte:
, onde
COL1
é a coluna pela qual você está ordenando.Ter um índice
(COL1, PK)
melhorará muito esta consulta.fonte
fonte
LEFT JOIN a tabela para si mesma, com a condição de junção resolvida de forma que a linha correspondida na versão junta da tabela esteja uma linha anterior, para sua definição particular de "anterior".
Update: A princípio, pensei que você gostaria de manter todas as linhas, com NULLs para a condição em que não havia linha anterior. Ao lê-lo novamente, você só deseja que as linhas sejam eliminadas, então você deve uma junção interna em vez de uma junção à esquerda.
Atualizar:
As versões mais recentes do Sql Server também têm as funções LAG e LEAD Windowing que podem ser usadas para isso também.
fonte
fonte
A resposta selecionada só funcionará se não houver lacunas na sequência. No entanto, se você estiver usando um id gerado automaticamente, é provável que haja lacunas na sequência devido a inserções que foram revertidas.
Este método deve funcionar se você tiver lacunas
fonte