SQL BETWEEN è un operatore utilizzato per specificare un intervallo di valori da testare. Il valore restituito può essere inclusivo o compreso nell'intervallo. Oppure può essere al di fuori dell'intervallo se si aggiunge l'operatore NOT prima di esso. Funziona per date, date con ora, numeri e stringhe.
Puoi usarlo sulle clausole WHERE per quanto segue:
- SELEZIONA,
- INSERIRE (con SELEZIONA)
- AGGIORNAMENTO,
- ed ELIMINA.
Funziona anche per le clausole HAVING insieme a GROUP BY.
Ma se non stai attento, SQL BETWEEN può farti impazzire quando lo usi, specialmente con le date con il tempo.
Non preoccuparti, però. Abbiamo esempi per affrontare i problemi nell'utilizzo di SQL BETWEEN. Ma prima, i dati di esempio che ho usato provenivano da NOAA . Puoi richiedere gratuitamente i dati meteorologici da loro. Ho utilizzato i record di temperatura orari per gli Stati Uniti nell'anno 2010. Quindi, ho importato i dati CSV in SQL Server utilizzando SQL Server Management Studio. Ho rinominato le colonne e aggiunto un indice non in cluster.
Cominciamo.
Utilizzo di SQL TRA con date e orari
Questo deve essere l'elemento più cercato quando si ha a che fare con SQL BETWEEN. Useremo degli esempi per spiegare come funziona.
Suggerimento n. 1:per le colonne DATETIME, specifica sia la data che l'ora
UTILIZZO ERRATO
Cominciamo con l'uso sbagliato per sottolineare questo punto. Il seguente utilizzo di BETWEEN con colonne DATETIME darà risultati imprevisti.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND '01/02/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
La query restituisce i dati per 2 giorni da una stazione meteorologica vicino all'aeroporto internazionale O'Hare di Chicago. Si può notare l'intervallo tra un valore più basso (01/01/2010) e un valore più alto (01/02/2010). Ecco il set di risultati nella Figura 1.
Figura 1 . Set di risultati di una query che utilizza SQL TRA 2 date.
Ma dov'è il problema?
Dovrebbe essere un record orario per 2 giorni. Per questo motivo, il set di risultati dovrebbe avere 48 record. Ma nota che sono solo 24. Il problema risiede nell'elemento ora di DateHour colonna. Quando non specifichi l'ora in una colonna DATETIME, presuppone le 00:00 o le 00:00. Inoltre, tieni presente che i dati sono iniziati il 1 gennaio 2010, alle 01:00, non alle 00:00.
Quindi, internamente, SQL Server utilizzava DateHour TRA '01/01/2010 00:00:00.000′ E '01/02/2010 00:00:00.000′ . Come lo sappiamo?
LA DATA È IN REALTA' UNA STRINGA
Esatto.
I valori di data racchiusi tra virgolette singole non sono in realtà date ma stringhe . SQL Server utilizza la conversione implicita per convertire la stringa in DATETIME. Dopo la conversione, la parte temporale verrà aggiunta alla data.
Esaminiamo con Includi piano di esecuzione effettivo . Premi Ctrl-M in SQL Server Management Studio, quindi riesegui l'esempio precedente.
Quando viene visualizzato il piano di esecuzione, fai clic con il pulsante destro del mouse su Ricerca indice operatore e seleziona Proprietà . Vedi figura 2.
Figura 2 . Conversione implicita di una stringa in DATETIME. È nascosto nel piano di esecuzione di una query utilizzando BETWEEN.
Quindi espandi Cerca predicati . Le porzioni riquadrate della Figura 2 mostrano la conversione implicita delle 2 stringhe in DATETIME. Poiché la conversione implicita viene eseguita internamente , i neofiti si confondono perché le loro aspettative nel set di risultati non vengono soddisfatte.
USO CORRETTO
L'esempio seguente restituirà i record orari tra le 8:00 e le 12:00 del 2 gennaio 2010.
SELECT * FROM TemperatureData
WHERE DateHour BETWEEN '01/02/2010 08:00' AND '01/02/2010 12:00'
AND Latitude = 41.995
AND Longitude = -87.9336;
È necessario specificare la parte temporale, soprattutto quando le date sono le stesse. Oppure i risultati attesi non si verificheranno.
Per restituire i record per l'intera giornata, questo non funzionerà:
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour = '06/01/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
Restituirà solo 1 record:quello del 1 giugno 2010 alle 00:00. Ma usando BETWEEN con gli orari specificati, puoi restituire il record di ogni ora per l'intera giornata. Vedi il prossimo esempio.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010 00:00' AND '06/01/2010 23:00'
AND Latitude = 41.995
AND Longitude = -87.9336;
Si noti che ho specificato solo fino alle 23:00. Se i tuoi dati utilizzano qualsiasi ora del giorno, utilizza 23:59 o 23:59 nel valore più alto dell'intervallo. Specifica i secondi anche se ne hai bisogno.
Suggerimento n. 2:considera il tipo di dati DATE
Se non hai bisogno della parte temporale, considera invece il tipo di dati DATE. Ed eviterai i problemi sopra menzionati.
SQL BETWEEN con numeri
Passiamo ai numeri.
Suggerimento n. 3:includi la parte decimale per valori non interi
SELECT
DateHour
,[Hourly_Heating_Degree_Hours]
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND '06/5/2010 23:00'
AND [Hourly_Heating_Degree_Hours] BETWEEN 5.0 AND 7.0
AND Latitude = 41.995
AND Longitude = -87.9336;
Notare l'aggiunta di un'altra condizione che coinvolge i numeri. I risultati saranno ulteriormente limitati a 5 e 7 gradi.
Quando si utilizzano i tipi di dati DECIMAL, MONEY o FLOAT, specificare la parte decimale anche se è zero, ad esempio 52.00 o 10.0000. In questo modo eviti la conversione implicita ai tipi di dati di destinazione DECIMAL, MONEY o FLOAT.
SQL TRA con stringhe
Suggerimento n. 4:per le stringhe, l'intervallo è basato sulle regole di confronto
Con le stringhe, BETWEEN valuta i valori in base all'ordine alfabetico. 'A' è il minimo e 'Z' è il massimo. Puoi anche dire che in generale, la valutazione si basa sulla confronto. Perché l'inglese non è l'unica lingua supportata da SQL Server. Fascicolazione fornisce regole di ordinamento, maiuscole e minuscole e sensibilità all'accento. Usiamo AdventureWorks database per questo esempio. Controlla il codice qui sotto e il risultato nella Figura 3.
USE AdventureWorks
GO
SELECT
LastName
,FirstName
,MiddleName
FROM Person.Person
WHERE Lastname BETWEEN 'Spanaway' AND 'Splane'
ORDER BY LastName;
Figura 3 . Set di risultati di una query che utilizza BETWEEN con stringhe.
L'intervallo copre il cognome Spanaway . Ma dov'è Splane ? È inesistente nel database. Quindi, il risultato ha raggiunto solo Spicer .
Suggerimenti per SQL BETWEEN per tutti i tipi di dati supportati
Sia che tu stia utilizzando BETWEEN per date, numeri o stringhe, ci sono cose comuni di cui dovresti essere a conoscenza. Questo potrebbe essere buon senso, ma succede ancora per errore. Leggi come questo può accadere.
Suggerimento n. 5:entrambi i valori di inizio e fine non possono essere NULL
BETWEEN ha bisogno dei valori iniziali e finali per l'intervallo. Ciascuno dovrebbe avere un valore che non è NULL. Di seguito è riportato un esempio con un valore finale NULL.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND NULL;
Questo può accadere se chiami l'istruzione SELECT da un'app o da una stored procedure e non l'hai convalidata correttamente.
Suggerimento n. 6:il valore iniziale non può essere maggiore del valore finale
Non verrà restituito nulla anche se entrambi i valori non sono NULL, ma l'intervallo è invertito. Ecco un esempio.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/30/2010' AND '01/01/2010';
A parte le date, anche le seguenti espressioni non restituiranno un risultato:
- valore TRA 100 E -200. Perché -200 è inferiore a 100.
- lavora TRA 'Zookeeper' E 'Accountant'. Perché 'Z' è maggiore di 'A'.
Suggerimento n. 7:i valori dell'intervallo devono essere gli stessi tipi di dati
A volte, i controlli dell'interfaccia utente hanno un output imprevisto. Oppure abbiamo appena preso la proprietà sbagliata. E se non lo controlliamo prima di passarlo a SQL Server, potrebbe verificarsi una situazione come questa:
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND 'Saturday, June 5, 2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
Si verificherà un errore di conversione da una stringa di caratteri a una data.
Quindi, la lezione dal suggerimento n. 5 al n. 7 è convalidare i valori di inizio e fine dell'intervallo .
Suggerimento n. 8:utilizzare NOT BETWEEN per escludere valori
Considera un altro esempio.
SELECT
MONTH(DateHour) AS [Month]
,round(AVG([Hourly_Heating_Degree_Hours]),2) AS AverageTemperature
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010 00:00' AND '06/30/2010 23:00'
AND DateHour NOT BETWEEN '05/01/2010 00:00' AND '05/31/2010 23:00'
AND Latitude = 41.995
AND Longitude = -87.9336
GROUP BY MONTH(DateHour);
Ciò restituirà la media mensile da gennaio a giugno ma escluderà maggio. L'esclusione dei record di maggio 2010 è resa possibile da NOT BETWEEN. Ecco il set di risultati in Figura 4.
Figura 4 . Set di risultati di una query che utilizza NOT BETWEEN.
SQL FRA rispetto ad altri operatori
Suggerimento n. 9:usa IN se hai bisogno di un elenco e non di un intervallo
L'operatore IN determina se un valore corrisponde a qualsiasi valore in un elenco o in una sottoquery. Nel frattempo, l'utilizzo di NOT IN controlla se un valore non corrisponde.
Entrambi gli operatori BETWEEN e IN filtrano i dati in base a più valori. Ma la differenza sta nell'insieme di valori abbinati. BETWEEN utilizza un intervallo. Ma IN utilizza valori separati da virgole in un elenco o righe in una sottoquery.
Controlla l'esempio qui sotto.
SELECT
DateHour
,[Hourly_Heating_Degree_Hours]
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND '06/5/2010 23:00'
AND [Hourly_Heating_Degree_Hours] IN (5.2, 6, 7, 3.7)
AND Latitude = 41.995
AND Longitude = -87.9336;
Guarda l'elenco dei valori utilizzati da IN. Non è necessario che sia un elenco di valori crescenti. L'ultimo valore della lista (3.7) è anche il minimo tra i numeri.
Suggerimento n. 10:scegli tra BETWEEN o>=con <=
In fase di esecuzione, SQL Server converte BETWEEN in>=con <=operatori. Come lo sappiamo?
Guarda il codice qui sotto.
SELECT
DateHour
,AVG(Hourly_Heating_Degree_Hours) AS AverageTemp
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010 08:00' AND '01/01/2010 12:00'
GROUP BY DateHour;
SELECT
DateHour
,AVG(Hourly_Heating_Degree_Hours) AS AverageTemp
FROM TemperatureData
WHERE DateHour >= '01/01/2010 08:00'
AND DateHour <= '01/01/2010 12:00'
GROUP BY DateHour;
Entrambe le query avranno lo stesso set di risultati di quello in Figura 5.
Figura 5 . Risultato impostato utilizzando BETWEEN o>=con <=.
Hanno anche lo stesso piano di esecuzione, come mostrato nella Figura 6.
Figura 6 . Piano di esecuzione di 2 query che confrontano l'uso di BETWEEN e>=e <=operatori.
Ma ecco il punto.
Nota il primo Indice Cerca nella Figura 6. Quindi, vedi Cerca predicati . Vedi la parola chiave BETWEEN? Non c'è nessuno, giusto? Perché viene convertito in>=con <=operatori. Questi sono gli operatori presenti nei Seek Predicates .
Ma c'è di più.
Se passi il mouse sulla seconda Ricerca indice operatore, vedrai le stesse proprietà della prima Ricerca indice .
Quindi, sembra che l'operatore BETWEEN sia una scorciatoia per>=con <=operatori . Digiterai di più se usi quest'ultimo. Vedrai che si verifica la stessa conversione quando BETWEEN viene utilizzato in numeri e stringhe.
Alla fine, sta a te se usi BETWEEN o gli operatori>=e <=. Il tempo di conversione necessario per convertire BETWEEN è trascurabile. Ma se non vuoi ancora quel tempo extra trascurabile, usa gli operatori>=e <=.
Linea inferiore
SQL BETWEEN è utile per recuperare i dati inclusi nell'intervallo. E non è così difficile da usare. Anche i valori DATETIME sono gestibili con BETWEEN. Assicurati solo di coprire correttamente la parte del tempo. È anche equivalente a usare>=con <=. Sta a te decidere quale preferisci utilizzare.
Puoi aggiungere questa pagina ai segnalibri per ottenere suggerimenti SQL BETWEEN per date, numeri e stringhe quando ne hai bisogno.
Se hai dei trucchi con BETWEEN che non abbiamo trattato, puoi condividerli con noi nella sezione Commenti. E se ti piace questo articolo, condividilo premendo i pulsanti dei social media.
Buona codifica a tutti!