PERGUNTA: Por que o SQL BETWEEN é inclusivo?
RESPOSTA: Como os projetistas da linguagem SQL tomaram uma péssima decisão de design, falharam em fornecer sintaxe que permitiria aos desenvolvedores especificar qual das 4 variantes de BETWEEN (fechada, semi-aberta-esquerda, semi-aberta-direita ou aberta). ) eles preferem.
RECOMENDAÇÃO: A menos que / até que o padrão SQL seja alterado, não use BETWEEN para datas / horas. Em vez disso, adquira o hábito de codificar comparações de intervalo DATE como condições independentes nos limites de início e fim do seu intervalo BETWEEN. Isso é um pouco detalhado, mas deixa você escrevendo condições que são intuitivas (com menor probabilidade de serem com erros) e claras para os otimizadores de banco de dados, permitindo que planos de execução ideais sejam determinados e índices sejam usados.
Por exemplo, se sua consulta está aceitando uma especificação do dia de entrada e deve retornar todos os registros que caíram nessa data, você codificaria como:
WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1
Tentar escrever a lógica usando BETWEEN arrisca problemas de desempenho e / ou código de buggy. Três erros comuns:
1) WHERE DATE_FIELD BETWEEN :dt AND :dt+1
Isso é quase certamente um bug - o usuário espera ver apenas registros para uma data específica, mas um dia será encerrado com um relatório contendo registros a partir das 12:00 do dia seguinte.
2) WHERE TRUNC(DATE_FIELD) = :dt
Dá a resposta certa, mas a aplicação da função para DATE_FIELD tornará inútil a maioria das estatísticas / indexação (embora algumas vezes os DBAs tentem ajudar adicionando índices baseados em funções aos campos de data - ainda gastando horas-homem e espaço em disco e adicionando sobrecarga ao DIU operações sobre a mesa)
3) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60
Tom Kyte, extraordinário guru da Oracle, recomenda esta solução menos que elegante (IMO). Funciona muito bem até que você gaste o dia todo para descobrir que "1-1 / 24/06/60" em uma consulta que fornece resultados incompletos ... ou até que você o use acidentalmente em um campo TIMESTAMP. Além disso, é um pouco proprietário; compatível com o tipo de dados DATE do Oracle (que acompanha o segundo), mas precisa ser ajustado com a precisão DATE / TIME de diferentes produtos de banco de dados.
SOLUÇÃO: Solicite ao comitê ANSI SQL que aprimore as especificações da linguagem SQL modificando a sintaxe BETWEEN para oferecer suporte à especificação de alternativas ao padrão CLOSED / INCLUSIVE. Algo assim faria o truque:
expr1 ENTRE expr2 [ INCL [USIVE] | EXCL [USIVE]] E expr3 [ INCL [USIVE] | EXCL [USIVE]]
Considere o quão fácil se torna para expressar WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(ou apenas WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)
Talvez ANSI SQL: 2015?