Eu tenho tabelas que contém transações para propriedades que são armazenadas como pares long long. (Existem mais colunas e pontos de dados do que no meu esquema de exemplo).
Uma solicitação comum é encontrar as transações que aconteceram a X milhas de um determinado ponto e recuperar apenas as 5 transações mais recentes que aconteceram para cada propriedade próxima.
Para fazer isso funcionar, decidi adicionar uma visão que encapsula essa lógica das mais recentes:
create or alter view dbo.v_example
with schemabinding as
select example_id
,transaction_dt
,latitude
,longitude
,latlong
,most_recent= iif(row_number() over (partition by latitude,longitude order by transaction_dt desc) < 5,1,null)
from dbo.example;
Portanto, uma consulta pode ser assim::
select *
from dbo.v_example
where latlong.STDistance(geography::Point(40,-74,4326)) <=1609.344e1
and most_recent = 1
Infelizmente, o SQL Server não quer usar o índice espacial quando eu consulto pela view. Se eu remover schemabinding
e tentar adicionar uma dica na exibição, recebo que o processador de consultas não pode criar um plano.
Como posso encapsular a lógica e ainda fazer com que ela use meu índice espacial?
Aqui está um db<>fiddle com dados de exemplo e formas de plano .
A tabela é muito maior e é muito mais lento varrê-la do que fazer uma busca de índice clusterizado e, em seguida, encontrar o ponto próximo.
Funções e visualizações da janela
Recentemente, respondi a uma pergunta diferente sobre visualizações e funções da janela, mas nem todas as respostas dadas se aplicam aqui.
Duas diferenças são que este exemplo usa
geography
tipos de dados e filtros na função de janela. A parte positiva aqui é que você não está vinculado à função window e pode usar algo comoCROSS APPLY
obter os resultados mais próximos para uma combinação delatitude
& .longitude
A pergunta anterior + resposta
Em resumo , a função da janela é calculada antes da aplicação da filtragem.
POR EXEMPLO
Informações extras podem ser encontradas nesta postagem do blog de 2013 de Paul White sobre funções e visualizações da janela.
Teste
Como primeiro teste, o resultado é claro ao omitir o
ROW_NUMBER()
da visãoResultando no plano de consulta de desempenho esperado.
DB<>Fiddle
Mas você obviamente ainda quer a filtragem adicional
Mantendo a função view + window
Você pode optar por adicionar a função de janela posteriormente, assim:
&
Novamente resultando no plano de execução esperado.
DB<>Fiddle
Usando uma função de valor de tabela em linha + função de janela
Resultando no plano de consulta que você esperava.
DB<>Fiddle
Usando uma função CTE + janela
Usando
CROSS APPLY
eTOP(4)
sem a função de janelaEu usei
top(4)
desde que o conjunto de resultados foi baseado em< 5
não<= 5
Ao usar o
CROSS APPLY
método, há mais um índice a ser adicionado, para remover o spool de índice e classificar:Escusado será dizer que você pode adicionar a
CROSS APPLY
solução a uma visualização e consultá-la da mesma maneira que costumava fazer, um exemplo disso aqui . Todos os exemplos acima em um DB<>Fiddle aqui .Comentário da solução final de MichaelB
DB<>Fiddle
&