Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

LAST_VALUE no SQL Server 2012 está retornando resultados estranhos


O SQL Server não sabe nem se importa com a ordem em que as linhas foram inseridas na tabela. Se você precisar de um pedido específico, sempre use ORDER BY . No seu exemplo ORDER BY é ambíguo, a menos que você inclua PK no ORDER BY . Além disso, LAST_VALUE pode retornar resultados estranhos se você não for cuidadoso - veja abaixo.

Você pode obter o resultado esperado usando MAX ou LAST_VALUE (SQLFiddle ). Eles são equivalentes neste caso:
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

O resultado desta consulta será o mesmo independentemente da ordem em que as linhas foram originalmente inseridas na tabela. Você pode tentar colocar INSERT declarações em ordem diferente no violino. Não afeta o resultado.

Além disso, LAST_VALUE se comporta não exatamente como você esperaria intuitivamente com a janela padrão (quando você tem apenas ORDER BY no OVER cláusula). A janela padrão é ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW , enquanto você esperava que fosse ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDING SEGUINTE . Aqui está uma resposta SO com um boa explicação . O link para esta resposta SO está na página do MSDN para LAST_VALUE . Assim, uma vez que a janela de linha é especificada explicitamente na consulta, ela retorna o que é necessário.

Se você quiser saber a ordem em que as linhas foram inseridas na tabela, acho que a maneira mais simples é usar IDENTIDADE . Então, a definição da sua tabela mudaria para isso:
CREATE TABLE Data 
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)

Quando você INSERIR nesta tabela você não precisa especificar o valor para PK , o servidor o geraria automaticamente. Garante que os valores gerados sejam únicos e crescentes (com parâmetro de incremento positivo), mesmo que você tenha muitos clientes inserindo na tabela ao mesmo tempo simultaneamente. Pode haver lacunas entre os valores gerados, mas a ordem relativa dos valores gerados informará qual linha foi inserida após qual linha.