Intervalos semi-abertos (ou semi-abertos, semi-fechados , meio-limitados ) ( [a,b)
, onde x
pertencem ao intervalo iff a <= x < b
) são bastante comuns na programação, pois possuem muitas propriedades convenientes.
Alguém pode oferecer uma justificativa que explica por que o SQL BETWEEN
usa um intervalo fechado ( [a,b]
)? Isso é esp. inconveniente para datas. Por que você se BETWEEN
comportaria assim?
Respostas:
Eu acho que inclusivo
BETWEEN
é mais intuitivo (e aparentemente os designers de SQL também) do que um intervalo semiaberto. Por exemplo, se eu disser "Escolha um número entre 1 e 10", a maioria das pessoas incluirá os números 1 e 10. O intervalo aberto é realmente particularmente confuso para os não desenvolvedores, porque é assimétrico. Ocasionalmente, o SQL é usado por não programadores para fazer consultas simples, e a semântica semi-aberta teria sido muito mais confusa para eles.fonte
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:
Considere o quão fácil se torna para expressar
WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(ou apenasWHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)Talvez ANSI SQL: 2015?
fonte
exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3
dessa maneira de manter o operador entre para que você saiba que é um predicado à distância, e o predicado da desigualdade garante que ele seja semi-aberto.Tanto inclusivo (
a <= x <= b
) quanto exclusivo (a < x < b
) são igualmente comuns, portanto, ao criar os padrões, eles simplesmente tiveram que escolher um. "Entre" no inglês comum é geralmente inclusivo, e uma instrução SQL deve ser semelhante a uma frase em inglês, portanto, inclusivo foi uma escolha sensata.fonte
a <= x < b
é meio aberto.O operador não é chamado
∩[a,b)
, é chamadoBETWEEN
, por isso é consideravelmente mais apropriado que sua semântica seja a da frase em inglês "está entre" do que a do predicado matemático "está em intervalo semiaberto".fonte
BETWEEN
operador não usa a semântica da frase em inglês "is between". Em inglês, "entre" é o tempo, espaço ou intervalo que separa as coisas (ou seja, é exclusivo ). Se você tentar chutar um gol, a bola terá que ir entre os postes para marcar. Se você acertar o post sem passar entre eles - nenhuma pontuação para você.