Los intervalos semiabiertos (o medio abiertos, medio cerrados , medio acotados ) ( [a,b)
donde x
pertenece al intervalo iff a <= x < b
) son bastante comunes en la programación, ya que tienen muchas propiedades convenientes.
¿Alguien puede ofrecer una justificación que explique por qué SQL BETWEEN
utiliza un intervalo cerrado ( [a,b]
)? Esto es especialmente inconveniente para las fechas. ¿Por qué te BETWEEN
habrías comportado así?
Respuestas:
Creo que inclusivo
BETWEEN
es más intuitivo (y aparentemente, también lo hicieron los diseñadores de SQL) que un intervalo semiabierto. Por ejemplo, si digo "Elija un número entre 1 y 10", la mayoría de las personas incluirán los números 1 y 10. El intervalo abierto es particularmente confuso para los no desarrolladores porque es asimétrico. Los no programadores utilizan ocasionalmente SQL para realizar consultas simples, y la semántica semiabierta habría sido mucho más confusa para ellos.fuente
PREGUNTA: ¿Por qué el SQL ENTRE es inclusivo?
RESPUESTA: Debido a que los diseñadores del lenguaje SQL tomaron una mala decisión de diseño, en el sentido de que no pudieron entregar una sintaxis que permitiera a los desarrolladores especificar cuál de las 4 variantes de ENTRE (cerrado, semiabierto a la izquierda, semiabierto a la derecha o abierto ) preferirían
RECOMENDACIÓN: A menos que / hasta que se modifique el estándar SQL, no use ENTRE las fechas / horas. En su lugar, adopte el hábito de codificar las comparaciones de rango DATE como condiciones independientes en los límites inicial y final de su rango ENTRE. Esto es un poco detallado, pero lo dejará escribiendo condiciones que son intuitivas (por lo tanto, menos propensas a tener errores) y claras para los optimizadores de la base de datos, lo que permite determinar planes de ejecución óptimos e índices que se utilizarán.
Por ejemplo, si su consulta acepta una especificación del día de entrada y debe devolver todos los registros que cayeron en esa fecha, codificaría como:
WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1
Tratar de escribir la lógica usando ENTRE arriesga problemas de rendimiento y / o código defectuoso. Tres pasos en falso comunes:
1)
WHERE DATE_FIELD BETWEEN :dt AND :dt+1
Esto es casi seguro que es un error: el usuario espera ver solo los registros de una fecha en particular, sin embargo, un día terminará con un informe que contiene registros de las 12:00 a.m. del día siguiente.
2)
WHERE TRUNC(DATE_FIELD) = :dt
Da la respuesta correcta, pero la aplicación de la función a DATE_FIELD hará que la mayoría de las indexaciones / estadísticas sean inútiles (aunque a veces los DBA intentarán ayudar agregando índices basados en funciones a los campos de fecha, lo que aún consumirá horas hombre y espacio en disco y agregará gastos generales al DIU operaciones en la mesa)
3)
WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60
Tom Kyte, extraordinario gurú de Oracle, recomienda esta solución poco elegante (IMO). Funciona muy bien hasta que pasa todo el día para encontrar ese "1-1 / 24/06/60" en una consulta que da resultados incompletos ... o hasta que lo use accidentalmente en un campo TIMESTAMP. Además, es un poco patentado; compatible con el tipo de datos DATE de Oracle (que sigue al segundo), pero debe ajustarse a la precisión DATE / TIME de diferentes productos de bases de datos.
SOLUCIÓN: Solicite al comité ANSI SQL que mejore las especificaciones del lenguaje SQL modificando la sintaxis ENTRE para admitir la especificación de alternativas al valor predeterminado CERRADO / INCLUSIVO. Algo así haría el truco:
Considere cuán fácil se vuelve expresar
WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(o simplementeWHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)Tal vez ANSI SQL: 2015?
fuente
exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3
la forma en que puedes mantener el operador intermedio para que sepas que es un predicado a distancia, y el predicado de desigualdad asegura que esté semi abierto.Tanto inclusivo (
a <= x <= b
) como exclusivo (a < x < b
) son casi igualmente comunes, por lo que al hacer los estándares simplemente tenían que elegir uno. "Entre" en inglés común es típicamente inclusivo, y una declaración SQL está destinada a leerse de manera similar a una oración en inglés, por lo que inclusivo fue una elección sensata.fuente
a <= x < b
está medio abierto.El operador no se llama
∩[a,b)
, se llamaBETWEEN
, por lo que es mucho más apropiado que su semántica sea la de la frase inglesa "está entre" que la del predicado matemático "está en intervalo semiabierto".fuente
BETWEEN
operador no utiliza la semántica de la frase inglesa "is between". En inglés "entre" es el tiempo, el espacio o el intervalo que separa las cosas (es decir, es exclusivo ). Si intentas patear un gol, la pelota debe ir entre los postes para anotar. Si golpeas la publicación que no pasa entre ellos, no hay puntaje para ti.