sql >> Database teknologi >  >> RDS >> Database

SQL MELLEM-Smarte tips til at scanne efter en række værdier

SQL BETWEEN er en operator, der bruges til at angive en række værdier, der skal testes. Den returnerede værdi kan være inklusive eller inden for området. Eller det kan være uden for området, hvis du tilføjer NOT-operatoren før det. Det virker for datoer, datoer med tid, tal og strenge.

Du kan bruge det på WHERE-sætninger til følgende:

  • VÆLG,
  • INSERT (med SELECT)
  • OPDATERING,
  • og SLET.

Det virker også for HAVING-sætninger sammen med GROUP BY.

Men hvis du ikke er forsigtig, kan SQL BETWEEN gøre dig skør, når du bruger det, især med datoer med tid.

Du skal dog ikke bekymre dig. Vi har eksempler til at håndtere gotchas ved at bruge SQL BETWEEN. Men før det kom prøvedataene, jeg brugte, fra NOAA . Du kan anmode om vejrdata gratis fra dem. Jeg brugte timetemperaturregistreringerne for USA i år 2010. Derefter importerede jeg CSV-dataene til SQL Serveren ved hjælp af SQL Server Management Studio. Jeg omdøbte kolonnerne og tilføjede et ikke-klynget indeks.

Lad os begynde.

Brug af SQL BETWEEN med datoer og klokkeslæt

Dette må være det mest søgte emne, når du har at gøre med SQL BETWEEN. Vi vil bruge eksempler til at forklare, hvordan det virker.

Tip #1:For DATETIME-kolonner skal du angive både dato og klokkeslæt

FORKERT BRUG

Lad os starte med den forkerte brug for at understrege dette punkt. Følgende brug af BETWEEN med DATETIME-kolonner vil give uventede resultater.


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;


Forespørgslen returnerer data for 2 dage fra en vejrstation nær O'Hare International Airport i Chicago. Du kan bemærke intervallet mellem en lavere værdi (01/01/2010) og en højere værdi (01/02/2010). Her er resultatet sat i figur 1.

Figur 1 . Resultatsæt af en forespørgsel, der bruger SQL BETWEEN 2 datoer.

Men hvor er problemet?

Det formodes at være en timerekord i 2 dage. Derfor skulle resultatsættet have 48 rekorder. Men bemærk, at det kun er 24. Problemet ligger i tidselementet i DateHour kolonne. Når du ikke angiver tidspunktet i en DATETIME-kolonne, antager det 00:00 eller 12:00 AM. Bemærk også, at dataene startede den 1. januar 2010 kl. 01:00, ikke kl. 12:00.

Så internt brugte SQL Server DateHour MELLEM ’01/01/2010 00:00:00.000′ OG ’01/02/2010 00:00:00.000′ . Hvordan ved vi det?

DATOEN ER FAKTISK EN STRING

Det er rigtigt.

Datoværdierne i enkelte anførselstegn er egentlig ikke datoer, men strenge . SQL Server bruger implicit konvertering til at konvertere strengen til DATETIME. Efter konverteringen vil tidsdelen blive tilføjet til datoen.

Lad os inspicere med Inkluder faktisk udførelsesplan . Tryk på Ctrl-M i SQL Server Management Studio, og kør derefter det forrige eksempel igen.

Når udførelsesplanen vises, skal du højreklikke på Indekssøgning operatør og vælg Egenskaber . Se figur 2.

Figur 2 . Implicit konvertering af en streng til DATETIME. Det er skjult i udførelsesplanen for en forespørgsel, der bruger BETWEEN.

Udvid derefter Søg prædikater . De indrammede dele af figur 2 viser den implicitte konvertering af de 2 strenge til DATETIME. Da implicit konvertering udføres internt , nybegyndere bliver forvirrede over, hvorfor deres forventninger til resultatsættet ikke bliver opfyldt.

KORREKT BRUG

Eksemplet nedenfor returnerer timeregistreringerne mellem kl. 8:00 og 12:00 den 2. januar 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;


Du skal angive tidsdelen, især når datoerne er de samme. Ellers vil dine forventede resultater ikke ske.

For at returnere registreringerne for hele dagen, virker dette ikke:


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour = '06/01/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;


Den returnerer kun 1 post – den for 1. juni 2010 kl. 12.00. Men ved at bruge BETWEEN med de angivne tidspunkter kan du returnere hver times rekord for hele dagen. Se næste eksempel.


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;


Bemærk, at jeg kun har angivet op til 23:00. Hvis dine data bruger et hvilket som helst tidspunkt på dagen, skal du bruge 23:59 eller 23:59 i den højeste værdi af området. Angiv også sekunderne, hvis du har brug for det.

Tip #2:Overvej datatypen DATE

Hvis du ikke har brug for tidsdelen, skal du overveje datatypen DATE i stedet for. Og du vil undgå de problemer, der er nævnt ovenfor.

SQL MELLEM med numre

Lad os gå videre til tallene.

Tip #3:Inkluder decimaldelen for ikke-heltalsværdier


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;


Bemærk tilføjelsen af ​​en anden betingelse, der involverer tal. Resultaterne vil yderligere være begrænset til 5 og 7 grader.

Når du bruger datatyperne DECIMAL, MONEY eller FLOAT, skal du angive decimaldelen, selvom den er nul, f.eks. 52,00 eller 10,0000. På denne måde undgår du implicit konvertering til måldatatyperne DECIMAL, MONEY eller FLOAT.

SQL MELLEM med strenge

Tip #4:For strenge er rækkevidde baseret på sortering

Med strenge evaluerer BETWEEN værdier baseret på alfabetisk rækkefølge. 'A' er mindst og 'Z' er størst. Man kan også sige, at evaluering generelt er baseret på sammenstilling. Fordi engelsk ikke er det eneste sprog, SQL Server understøtter. Samling giver sorteringsregler, kasus- og accentfølsomhed. Lad os bruge AdventureWorks database for dette eksempel. Tjek koden nedenfor og resultatet i figur 3.


USE AdventureWorks
GO

SELECT 
 LastName
,FirstName
,MiddleName
FROM Person.Person
WHERE Lastname BETWEEN 'Spanaway' AND 'Splane'
ORDER BY LastName;

Figur 3 . Resultatsæt af en forespørgsel, der bruger BETWEEN med strenge.

Området dækker efternavnet Spanaway . Men hvor er Splane ? Det er ikke-eksisterende i databasen. Så resultatet nåede kun op til Spicer .

SQL MELLEM Tips til alle understøttede datatyper

Uanset om du bruger BETWEEN til datoer, tal eller strenge, er der almindelige ting, du bør være opmærksom på. Dette kunne være sund fornuft, men det sker stadig ved en fejl. Læs om, hvordan dette kan ske.

Tip #5:Både start- og slutværdier kan ikke være NULL

MELLEM kræver start- og slutværdier for området. Hver skal have en værdi, der ikke er NULL. Der er et eksempel med en NULL slutværdi nedenfor.


SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND NULL;


Dette kan ske, hvis du kalder SELECT-sætningen fra en app eller en lagret procedure, og du ikke validerede den korrekt.

Tip #6:Startværdien kan ikke være større end slutværdien

Intet vil også blive returneret, hvis begge værdier ikke er NULL, men intervallet er omvendt. Her er et eksempel.

SELECT 
 DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/30/2010' AND '01/01/2010';


Bortset fra datoer vil følgende udtryk heller ikke returnere et resultat:

  • værdi MELLEM 100 OG -200. Fordi -200 er lavere end 100.
  • arbejde MELLEM 'Zookeeper' OG 'Revisor'. Fordi 'Z' er større end 'A'.

Tip #7:Områdeværdier bør være de samme datatyper

Nogle gange har brugergrænsefladekontroller uventet output. Eller vi har bare hentet den forkerte ejendom. Og hvis vi ikke tjekker det, før vi sender det til SQL Server, kan en situation som denne ske:


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;

En konverteringsfejl fra en tegnstreng til en dato vil opstå.

Så lektionen fra tip #5 til #7 er at validere start- og slutværdierne for området .

Tip #8:Brug NOT BETWEEN for at ekskludere værdier

Overvej et andet eksempel.


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);


Dette vil returnere det månedlige gennemsnit fra januar til juni, men vil ekskludere maj. Udelukkelse af posterne for maj 2010 er muliggjort af NOT BETWEEN. Her er resultatet sat i figur 4.

Figur 4 . Resultatsæt af en forespørgsel med NOT BETWEEN.

SQL MELLEM sammenlignet med andre operatører

Tip #9:Brug IN, hvis du har brug for en liste og ikke en række

IN-operatoren bestemmer, om en værdi matcher en værdi i en liste eller underforespørgsel. I mellemtiden kontrollerer brugen af ​​NOT IN, om en værdi ikke stemmer overens.

Både BETWEEN- og IN-operatørerne filtrerer data baseret på flere værdier. Men forskellen ligger i det sæt af værdier, der matches. BETWEEN bruger et interval. Men IN bruger kommaseparerede værdier i en liste eller rækker i en underforespørgsel.

Tjek eksemplet nedenfor.

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;


Se på listen over værdier, der bruges af IN. Det behøver ikke at være en liste over stigende værdier. Den sidste værdi i listen (3.7) er også den mindste blandt tallene.

Tip #10:Vælg mellem BETWEEN eller>=med <=

Ved kørsel konverterer SQL Server BETWEEN til>=med <=operatorer. Hvordan ved vi det?

Se koden nedenfor.


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;


Begge forespørgsler vil have det samme resultatsæt som det i figur 5.

Figur 5 . Resultat indstillet ved at bruge enten BETWEEN eller>=med <=.

De har også den samme udførelsesplan, som ses i figur 6.

Figur 6 . Udførelsesplan med 2 forespørgsler, der sammenligner brugen af ​​BETWEEN, og>=og <=operatorer.

Men her er sagen.

Læg mærke til det første indeks Søg operatør i figur 6. Se derefter Søg prædikater . Kan du se søgeordet MELLEM? Der er ingen, vel? Fordi det konverteres til>=med <=operatorer. Det er de operatører, der er til stede i Seek Predicates .

Men der er mere.

Hvis du holder musen hen til den anden indekssøgning operatør, vil du se de samme egenskaber som den første indekssøgning .

Så det ser ud til, at BETWEEN operatoren er en genvej til>=med <=operatorer . Du skriver mere, hvis du bruger sidstnævnte. Du vil se den samme konvertering ske, når BETWEEN bruges i tal og strenge.

I sidste ende er det op til dig, om du bruger BETWEEN eller>=og <=operatorerne. Konverteringstiden det tager at konvertere BETWEEN er ubetydelig. Men hvis du stadig ikke vil have den ekstra ubetydelige tid, så brug>=og <=operatorerne.

Bundlinje

SQL BETWEEN er god til at hente data inklusive området. Og det er ikke så svært at bruge. Selv DATETIME-værdierne kan håndteres med BETWEEN. Bare sørg for at dække timeportionen ordentligt. Det svarer også til at bruge>=med <=. Det er op til dig, hvad du foretrækker at bruge.

Du kan bogmærke denne side for at få SQL BETWEEN-tip til datoer, tal og strenge, når du har brug for dem.

Hvis du har nogle tricks med BETWEEN, som vi ikke dækkede, kan du dele dem med os i kommentarsektionen. Og hvis du kan lide denne artikel, så del den ved at trykke på knapperne på sociale medier.

God kodning, alle sammen!


  1. Hvordan fjerner du dubletter fra kommasepareret liste med regex i Oracle, men jeg vil ikke have dubletter værdier?

  2. PostgreSQL-forespørgsel meget langsom med grænse 1

  3. Hvordan forespørger man efter null-værdier i json-felttypen postgresql?

  4. Sådan eksporteres SQL Server-data fra tabel til en CSV-fil