SQL: TRA vs <= e> =


111

In SQL Server 2000 e 2005:

  • qual è la differenza tra queste due WHEREclausole?
  • quale dovrei usare su quali scenari?

Domanda 1:

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

Domanda 2:

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

(Modifica: il secondo Eventdate era originariamente mancante, quindi la query era sintatticamente sbagliata)



6
non proprio, la gestione di datetime è leggermente diversa, in più era per SQL Server 2008, e non c'è modo che Shyju possa esserne certo senza chiedere che la risposta sarebbe la stessa per le versioni precedenti.
Irfy

Risposte:


119

Sono identici: BETWEENè una scorciatoia per la sintassi più lunga nella domanda.

Usa una sintassi alternativa più lunga dove BETWEENnon funziona, ad es

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

(Nota <piuttosto che <=nella seconda condizione.)


19
Forse dovresti sottolineare che la seconda condizione è "<". Mi ci è voluto del tempo per individuare la differenza.
zendar

21
Vorrei aggiungere che consiglio vivamente di non utilizzare mai BETWEEN a meno che tu non abbia a che fare con il tipo di dati DATE o abbia altrimenti garantito che i tuoi valori datetime non avranno mai una componente temporale. Essere coerenti su questo renderà meno probabile che utilizzerai BETWEEN per errore invece di> = e <e otterrai alcuni dati nella query che non intendevi o penserai di ricevere un giorno in più di dati quando non sei ...
Aaron Bertrand

1
Ci sarebbe un secondo passaggio del compilatore quando BETWEEN viene convertito in condizionali? Capisco che sia un po 'pedante, ma ci sarebbe un sovraccarico aggiuntivo?
James Scott

1
@xmashallax perché lo sono? Come non lo sono?
Tony Andrews,

2
Strano ... penso di essere stato confuso dalla domanda, dalla scrittura della risposta, dai commenti e dal fatto che il mio codice ovviamente ha un bug ora =)
xmashallax

37

Loro sono la stessa cosa.

Una cosa a cui fare attenzione è che se stai usando questo contro un DATETIME, la corrispondenza per la data di fine sarà l'inizio della giornata:

<= 20/10/2009

non è lo stesso di:

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

(che sarebbe partita contro <= 20/10/2009 00:00:00.000)


In tal caso, puoi semplicemente utilizzare tra '2009-10-20' e '2009-10-21' per catturare il giorno
David Andrei Ned

4
@DavidAndreiNed che corrisponderebbe anche a "2009-10-21 00: 00: 00.000", probabilmente non quello che desideri.
Hans Ke st ing

2
Si desidera che il campo TRA '2009-10-20 00:00:00' E '2009-10-20 23:59:59' o il campo> = '2009-10-20 00:00:00' E campo <= "2009-10-20 23:59:59" per essere assolutamente certi.
geilt

@geilt I tuoi esempi mancherebbero tutto ciò che si è verificato entro l'ultimo secondo della giornata ... cioè: tra le 23:59:59 e le 00:00:00 del giorno successivo.
Seth Flowers

00:00:00 è l'inizio del giorno successivo e perché uso> = e <= e non> o <. Ma se intendevi microsecondi e li memorizzi, allora dovresti mettere anche l'ultimo e l'ultimo microsecondo.
geilt

14

Sebbene BETWEENsia di facile lettura e manutenzione, raramente ne consiglio l'uso perché è un intervallo chiuso e come accennato in precedenza questo può essere un problema con le date, anche senza componenti temporali.

Ad esempio, quando si ha a che fare con dati mensili è spesso comune confrontare le date BETWEEN first AND last, ma in pratica questo è solitamente più facile da scrivere dt >= first AND dt < next-first(che risolve anche il problema della parte temporale), poiché determinare di lastsolito è un passo più lungo della determinazione next-first(sottraendo un giorno) .

Inoltre, un altro problema è che i limiti inferiore e superiore devono essere specificati nell'ordine corretto (cioè BETWEEN low AND high).


4

In genere, non c'è differenza: la BETWEENparola chiave non è supportata su tutte le piattaforme RDBMS, ma se lo è, le due query dovrebbero essere identiche.

Dal momento che sono identici, non c'è davvero alcuna distinzione in termini di velocità o altro: usa quello che ti sembra più naturale.


4

Come menzionato da @marc_s, @Cloud, et al. sono fondamentalmente gli stessi per un intervallo chiuso.

Ma i valori di tempo frazionari possono causare problemi con un intervallo chiuso (maggiore o uguale e meno o uguale ) rispetto a un intervallo semiaperta (maggiore o uguale e minore di ) con un valore finale dopo la ultimo istante possibile.

Quindi per evitare che la query debba essere riscritta come:

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

Poiché BETWEENnon funziona per intervalli semiaperti, do sempre uno sguardo attento a qualsiasi query di data / ora che lo utilizza, poiché probabilmente è un errore.


4

Ho una leggera preferenza per BETWEENperché rende immediatamente chiaro al lettore che stai controllando un campo per un intervallo . Ciò è particolarmente vero se hai nomi di campo simili nella tua tabella.

Se, diciamo, la nostra tabella ha sia a transactiondateche a transitiondate, se leggo

transactiondate between ...

So immediatamente che entrambe le estremità del test sono contro questo campo.

Se leggo

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

Devo prendermi un momento in più per assicurarmi che i due campi siano gli stessi.

Inoltre, quando una query viene modificata nel tempo, un programmatore sciatto potrebbe separare i due campi. Ho visto molte domande che dicono qualcosa di simile

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

Se lo provano con una BETWEEN, ovviamente, sarà un errore di sintassi e sarà prontamente risolto.


3

Penso che l'unica differenza sia la quantità di zucchero sintattico su ogni query. BETWEEN è solo un modo intelligente per dire esattamente lo stesso della seconda query.

Potrebbero esserci alcune differenze specifiche RDBMS di cui non sono a conoscenza, ma non la penso davvero.


2

Logicamente non ci sono differenze. Dal punto di vista delle prestazioni, tipicamente, sulla maggior parte dei DBMS, non ci sono differenze.



1

Disclaimer: tutto ciò che segue è solo aneddotico e tratto direttamente dalla mia esperienza personale. Chiunque si senta in grado di condurre un'analisi più empiricamente rigorosa è il benvenuto a portarla a termine e votare se lo sono. Sono anche consapevole del fatto che SQL è un linguaggio dichiarativo e non dovresti considerare COME viene elaborato il tuo codice quando lo scrivi, ma, poiché apprezzo il mio tempo, lo faccio.

Ci sono infinite affermazioni logicamente equivalenti, ma ne considererò tre (ish).

Caso 1: due confronti in un ordine standard (ordine di valutazione fisso)

A> = MinBound AND A <= MaxBound

Caso 2: zucchero sintattico (l'ordine di valutazione non è scelto dall'autore)

A TRA MinBound E MaxBound

Caso 3: due confronti in un ordine istruito (ordine di valutazione scelto al momento della scrittura)

A> = MinBound AND A <= MaxBound

O

A <= MaxBound AND A> = MinBound

Nella mia esperienza, il caso 1 e il caso 2 non presentano differenze consistenti o notevoli nelle prestazioni in quanto ignorano i set di dati.

Tuttavia, il caso 3 può migliorare notevolmente i tempi di esecuzione. In particolare, se stai lavorando con un set di dati di grandi dimensioni e hai qualche conoscenza euristica sul fatto che A sia più probabile che sia maggiore del MaxBound o minore del MinBound , puoi migliorare notevolmente i tempi di esecuzione utilizzando il caso 3 e ordinando i confronti di conseguenza.

Un caso d'uso che ho è l'interrogazione di un ampio set di dati storici con date non indicizzate per i record all'interno di un intervallo specifico. Durante la scrittura della query, avrò una buona idea se esistono o meno più dati PRIMA dell'intervallo specificato o DOPO l'intervallo specificato e posso ordinare i miei confronti di conseguenza. I tempi di esecuzione sono stati ridotti fino alla metà a seconda delle dimensioni del set di dati, della complessità della query e della quantità di record filtrati dal primo confronto.


Ehm, cosa? Il caso 3 non condivide la stessa logica del caso 1 e del caso 2. Se vuoi vedere se Aè maggiore di entrambi i limiti, controlla semplicemente se Aè maggiore di MaxBound. Il tuo post necessita di alcuni aggiustamenti.
mickmackusa

Sembra che abbia fatto un errore di battitura sugli operatori di uguaglianza. Buona pesca.
LanchPad

0

In questo scenario col BETWEEN ... AND ...e col <= ... and col >= ...sono equivalenti.


SQL Standard definisce anche il predicato T461 Symmetric BETWEEN :

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

Transact-SQL non supporta questa funzionalità.

BETWEENrichiede che i valori siano ordinati. Per esempio:

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

<=>

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

D'altro canto:

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

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

Funziona esattamente come al solito BETWEENma dopo aver ordinato i valori di confronto.

db <> fiddle demo

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.