Revendo esta pergunta , parece que há muito trabalho que não deveria ser necessário. Eles estão tentando estender um intervalo com uma data. Em outros bancos de dados, você usaria apenas greatest
e least
..
least(extendDate,min), greatest(extendDate,max)
Quando eu tento usá-los, porém, recebo
'least' is not a recognized built-in function name.
'greatest' is not a recognized built-in function name.
Isso cobriria a extensão em qualquer direção.
Para os propósitos da pergunta, você ainda teria que fazer a substituição de intervalo exclusivo.
Eu só estou querendo saber como os usuários do SQL Server implementam padrões de consulta para imitar least
e greatest
funcionalidade.
- PostgreSQL
GREATEST
/LEAST
- MySQL
GREATEST
/LEAST
- MariaDB
GREATEST
LEAST
- DB2
GREATEST
LEAST
- Oráculo
GREATEST
LEAST
Você desdobra as condições em CASE
declarações ou existe uma extensão, complemento de terceiros ou licença da Microsoft que habilita essa funcionalidade?
Um método comum é usar a
VALUES
cláusula eCROSS APPLY
as duas colunas com alias como uma única coluna e, em seguida, obter oMIN
eMAX
de cada uma.Existem outras maneiras de escrevê-lo, por exemplo, usando
UNION ALL
No entanto, os planos de consulta resultantes parecem ser os mesmos.
O SQL Server agora dá suporte a essas duas funções no Azure SQL DB e, presumivelmente, elas estarão disponíveis no local para o SQL Server 2022.
Você também pode colocar os valores embutidos em uma subconsulta. Assim:
GREATEST
eLEAST
agora têm suporte no Azure SQL e terão suporte no SQL Server 2022.MENOS equivalente:
MAIOR equivalente:
Para sua informação, implementamos MAIOR e MENOS no Azure SQL DB e nas próximas versões do SQL Server:
https://learn.microsoft.com/en-us/sql/t-sql/functions/logical-functions-greatest-transact-sql?view=sql-server-ver15
Este seria um bom começo -
Eu pretendia adicionar um comentário à resposta do @ed-avis, mas não consegui, devido à falta de reputação, então postei isso como extensão da resposta dele.
Eu eliminei a desvantagem de "Irritantemente você tem que fazer funções separadas para cada tipo de dados." Usando SQL_VARIANT .
Aqui está minha implementação:
Além disso, esta função lida com NULL s como a versão postgresql.
Essa função pode ser adicionada ao banco de dados por conveniência, mas é 10 vezes mais lenta do que usar o
IIF
. Meus testes mostram que essa função com tipo exato ( datetime ) executa o mesmo que a versão sql_variant .PS Eu executo alguns testes no conjunto de dados de 350k valores e parece que o desempenho é o mesmo, sql_variant é um pouco mais rápido, mas acredito que seja apenas jitters.
Mas de qualquer forma a versão IIF é 10x mais rápida!!!
Eu não testei inline,
CASE WHEN
mas basicamente para t-sql IIF é o mesmo que case e iif get é convertido pelo otimizador para a expressão case.CONCLUSÃO: É mais rápido usar IIF se o desempenho for importante, mas para prototipagem, ou se a clareza do código for mais necessária, e não houver grandes cálculos envolvidos, desde que a função possa ser usada.
Eu crio funções definidas pelo usuário, por exemplo
Você também pode fazer um usando
sql_variant
em vez deint
, que funcionará com qualquer tipo. (Infelizmente, ele sofre com as regras de conversão de tipo 'úteis' do MSSQL, retornando sem sentido se chamado com(1, 'a')
em vez de um erro.) Pelo menos o desempenho comsql_variant
não parece pior do que a versão para um tipo específico.Embora possa funcionar em casos simples, existem vários problemas com essa abordagem:
iif
ou escrita à mãocase
é cerca de dez vezes mais rápida que a chamada de função.least
operador faz no Oracle e no MySQL, mas difere do Postgres. Mas essa blindagem contra null o torna mais detalhado (se você sabe que eles não serão null, um simplescase when @a <= @b then @a else @b end
funcionaria).Em suma, pode ser melhor escrever a
case
expressão à mão se o desempenho for importante. Eu até recorri à geração decase
instruções aninhadas no lado do cliente quando há vários valores para comparar.