SQL: ENTRE vs <= y> =

111

En SQL Server 2000 y 2005:

  • ¿Cuál es la diferencia entre estas dos WHEREcláusulas?
  • ¿Cuál debería usar en qué escenarios?

Consulta 1:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate BETWEEN '10/15/2009' AND '10/18/2009'

Consulta 2:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate >='10/15/2009'
  AND EventDate <='10/18/2009'

(Editar: originalmente faltaba el segundo Eventdate, por lo que la consulta era sintácticamente incorrecta)

Shyju
fuente
1
Este es un cuasi duplicado con stackoverflow.com/questions/1572840/sql-between-v1-and-v2
mjv
6
no realmente, el manejo de datetime es ligeramente diferente, además de eso fue para SQL Server 2008, y no hay forma de que Shyju pueda estar seguro sin preguntar que la respuesta sería la misma para versiones anteriores.
Irfy

Respuestas:

119

Son idénticos: BETWEENes una abreviatura de la sintaxis más larga de la pregunta.

Use una sintaxis alternativa más larga donde BETWEENno funcione, por ejemplo

Select EventId,EventName from EventMaster
where EventDate >= '10/15/2009' and EventDate < '10/18/2009'

(Tenga <en cuenta en lugar de <=en la segunda condición).

Tony Andrews
fuente
19
Quizás debería enfatizar que la segunda condición es '<'. Me tomó un tiempo notar la diferencia.
zendar
21
Agregaría que recomiendo encarecidamente no usar BETWEEN a menos que esté tratando con el tipo de datos DATE o haya garantizado de otra manera que sus valores de fecha y hora nunca tendrán un componente de hora. Ser coherente con esto hará que sea menos probable que use BETWEEN por error en lugar de> = y <, y obtenga algunos datos en la consulta que no quería, o piense que está obteniendo un día adicional de datos cuando no estás ...
Aaron Bertrand
1
¿Habría un segundo paso del compilador cuando BETWEEN se convierta en condicionales? Entiendo que esto es un poco pedante, pero ¿habría una sobrecarga adicional?
James Scott
1
@xmashallax porque lo son? ¿Cómo no lo son?
Tony Andrews
2
Extraño ... Creo que me confundí con la pregunta, la redacción de la respuesta, los comentarios y el hecho de que mi código obviamente tiene un error ahora =)
xmashallax
37

Ellos son iguales.

Una cosa a tener en cuenta es que si está usando esto contra un DATETIME, la coincidencia para la fecha de finalización será el comienzo del día:

<= 20/10/2009

no es lo mismo que:

<= 20/10/2009 23:59:59

(que podría coincidir en contra <= 20/10/2009 00:00:00.000)

Irfy
fuente
Simplemente puede usar entre '2009-10-20' y '2009-10-21' en ese caso para capturar el día
David Andrei Ned
4
@DavidAndreiNed que también coincidiría con '2009-10-21 00: 00: 00.000', probablemente no sea lo que quieres.
Hans Ke st ing
2
Querría el campo ENTRE '2009-10-20 00:00:00' Y '2009-10-20 23:59:59' o el campo> = '2009-10-20 00:00:00' Y el campo <= '2009-10-20 23:59:59' para estar absolutamente seguro.
geilt
@geilt Tus ejemplos perderían cualquier cosa que ocurriera en el último segundo del día ... es decir, entre las 23:59:59 y las 00:00:00 del día siguiente.
Seth Flowers
00:00:00 es el comienzo del día siguiente y por qué uso> = y <= y no> o <. Pero si te refieres a microsegundos y los almacenas, entonces querrás poner el último y último microsegundo también.
geilt
14

Aunque BETWEENes fácil de leer y mantener, rara vez recomiendo su uso porque es un intervalo cerrado y, como se mencionó anteriormente, esto puede ser un problema con las fechas, incluso sin componentes de tiempo.

Por ejemplo, cuando se trata de datos mensuales, a menudo es común comparar fechas BETWEEN first AND last, pero en la práctica esto suele ser más fácil de escribir dt >= first AND dt < next-first(lo que también resuelve el problema de la parte del tiempo), ya que determinar lastgeneralmente es un paso más largo que determinar next-first(restando un día) .

Además, otro problema es que los límites inferior y superior deben especificarse en el orden correcto (es decir BETWEEN low AND high).

Cade Roux
fuente
4

Normalmente, no hay diferencia: la BETWEENpalabra clave no es compatible con todas las plataformas RDBMS, pero si lo es, las dos consultas deben ser idénticas.

Dado que son idénticos, realmente no hay distinción en términos de velocidad o cualquier otra cosa: use el que le parezca más natural.

marc_s
fuente
4

Como lo mencionó @marc_s, @Cloud, et al. son básicamente los mismos para un rango cerrado.

Pero cualquier valor de tiempo fraccionario puede causar problemas con un rango cerrado (mayor o igual y menor o igual ) en lugar de un rango medio abierto (mayor o igual y menor que ) con un valor final después del último instante posible.

Entonces, para evitar que la consulta deba reescribirse como:

SELECT EventId, EventName
  FROM EventMaster
 WHERE (EventDate >= '2009-10-15' AND
        EventDate <  '2009-10-19')    /* <<<== 19th, not 18th */

Dado BETWEENque no funciona para intervalos semiabiertos, siempre analizo detenidamente cualquier consulta de fecha / hora que lo use, ya que probablemente sea un error.

devstuff
fuente
4

Tengo una ligera preferencia por BETWEENporque deja en claro instantáneamente al lector que está marcando un campo para un rango . Esto es especialmente cierto si tiene nombres de campo similares en su tabla.

Si, digamos, nuestra mesa tiene a transactiondatey a transitiondate, si leo

transactiondate between ...

Sé de inmediato que ambos extremos de la prueba están en contra de este campo.

Si leo

transactiondate>='2009-04-17' and transactiondate<='2009-04-22'

Tengo que tomarme un momento más para asegurarme de que los dos campos sean iguales.

Además, a medida que una consulta se edita con el tiempo, un programador descuidado podría separar los dos campos. He visto muchas consultas que dicen algo como

where transactiondate>='2009-04-17'
  and salestype='A'
  and customernumber=customer.idnumber
  and transactiondate<='2009-04-22'

Si intentan esto con un BETWEEN, por supuesto, será un error de sintaxis y se solucionará de inmediato.

Arrendajo
fuente
3

Creo que la única diferencia es la cantidad de azúcar sintáctica en cada consulta. BETWEEN es solo una forma hábil de decir exactamente lo mismo que en la segunda consulta.

Puede haber alguna diferencia específica de RDBMS que no conozco, pero realmente no lo creo.

pirocumulus
fuente
2

Lógicamente no hay ninguna diferencia. En cuanto al rendimiento, por lo general, en la mayoría de los DBMS, no hay ninguna diferencia.

mjv
fuente
1

Descargo de responsabilidad: todo lo que aparece a continuación es solo anecdótico y se extrae directamente de mi experiencia personal. Cualquiera que se sienta dispuesto a realizar un análisis más riguroso empíricamente puede llevarlo a cabo y votar en contra si yo lo hago. También soy consciente de que SQL es un lenguaje declarativo y se supone que no debes considerar CÓMO se procesa tu código cuando lo escribes, pero, como valoro mi tiempo, lo hago.

Hay infinitas declaraciones lógicamente equivalentes, pero consideraré tres (más o menos).

Caso 1: dos comparaciones en un orden estándar (orden de evaluación fijo)

A> = MinBound Y A <= MaxBound

Caso 2: Azúcar sintáctico (el orden de evaluación no lo elige el autor)

ENTRE MinBound Y MaxBound

Caso 3: dos comparaciones en un orden educado (orden de evaluación elegido en el momento de la escritura)

A> = MinBound Y A <= MaxBound

O

A <= MaxBound Y A> = MinBound

En mi experiencia, el Caso 1 y el Caso 2 no tienen diferencias consistentes o notables en el rendimiento, ya que ignoran el conjunto de datos.

Sin embargo, el Caso 3 puede mejorar considerablemente los tiempos de ejecución. En concreto, si se trabaja con un gran conjunto de datos y pasar a tener algún conocimiento heurístico acerca de si una es más probable que sea mayor que el MaxBound o menor que el MinBound puede mejorar notablemente los tiempos de ejecución mediante el uso de la caja 3 y ordenar las comparaciones en consecuencia.

Un caso de uso que tengo es consultar un gran conjunto de datos históricos con fechas no indexadas para registros dentro de un intervalo específico. Al escribir la consulta, tendré una buena idea de si existen más datos ANTES del intervalo especificado o DESPUÉS del intervalo especificado y puedo ordenar mis comparaciones en consecuencia. He tenido tiempos de ejecución reducidos a la mitad dependiendo del tamaño del conjunto de datos, la complejidad de la consulta y la cantidad de registros filtrados por la primera comparación.

LanchPad
fuente
¿Um que? El caso 3 no comparte la misma lógica que el caso 1 y el caso 2. Si desea ver si Aes mayor que ambos límites, simplemente verifique si Aes mayor que el MaxBound. Tu publicación necesita algunos ajustes.
mickmackusa
Parece que cometí un error tipográfico en los operadores de igualdad. Buena atrapada.
LanchPad
0

En este escenario col BETWEEN ... AND ...y col <= ... and col >= ...son equivalentes.


El estándar SQL define también el predicado T461 Symmetric BETWEEN :

 <between predicate part 2> ::=
 [ NOT ] BETWEEN [ ASYMMETRIC | SYMMETRIC ]
 <row value predicand> AND <row value predicand>

Transact-SQL no admite esta función.

BETWEENrequiere que los valores estén ordenados. Por ejemplo:

SELECT 1 WHERE 3 BETWEEN 10 AND 1
-- no rows

<=>

SELECT 1 WHERE 3 >= 10 AND 3 <= 1
-- no rows

Por otra parte:

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 1 AND 10;
-- 1

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 10 AND 1
-- 1

Funciona exactamente como lo normal BETWEENpero después de ordenar los valores de comparación.

db <> demostración de violín

Lukasz Szozda
fuente