sql >> Databasteknik >  >> RDS >> Database

SQL MELLAN-Smarta tips för att söka efter en rad värden

SQL BETWEEN är en operator som används för att ange ett värdeintervall som ska testas. Det returnerade värdet kan vara inklusive eller inom intervallet. Eller det kan vara utanför intervallet om du lägger till NOT-operatorn före den. Det fungerar för datum, datum med tid, siffror och strängar.

Du kan använda den på WHERE-satser för följande:

  • VÄLJ,
  • INSERT (med SELECT)
  • UPPDATERA,
  • och DELETE.

Det fungerar även för HAVING-satser tillsammans med GROUP BY.

Men om du inte är försiktig kan SQL BETWEEN göra dig galen när du använder den, särskilt med datum med tid.

Oroa dig inte. Vi har exempel för att hantera gotchas i att använda SQL BETWEEN. Men innan dess kom provdatan jag använde från NOAA . Du kan begära väderdata gratis från dem. Jag använde timtemperaturposterna för USA år 2010. Sedan importerade jag CSV-data till SQL Server med SQL Server Management Studio. Jag döpte om kolumnerna och lade till ett icke-klustrat index.

Låt oss börja.

Använda SQL BETWEEN med datum och tider

Detta måste vara det mest sökta objektet när man hanterar SQL BETWEEN. Vi kommer att använda exempel för att förklara hur det fungerar.

Tips #1:För DATETIME-kolumner, ange både datum och tid

FEL ANVÄNDNING

Låt oss börja med fel användning för att betona denna punkt. Följande användning av BETWEEN med DATETIME-kolumner kommer att ge oväntade resultat.


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;


Frågan returnerar data för 2 dagar från en väderstation nära O’Hare International Airport i Chicago. Du kan se intervallet mellan ett lägre värde (01/01/2010) och ett högre värde (01/02/2010). Här är resultatet i figur 1.

Figur 1 . Resultatuppsättning av en fråga som använder SQL MELLAN 2 datum.

Men var är problemet?

Det är tänkt att vara ett timrekord i 2 dagar. På grund av det borde resultatuppsättningen ha 48 rekord. Men observera att det bara är 24. Problemet ligger i tidselementet i DateHour kolumn. När du inte anger tiden i en DATETIME-kolumn antar den 00:00 eller 12:00 AM. Observera också att uppgifterna startade den 1 januari 2010, klockan 01:00, inte 12:00.

Så internt använde SQL Server DateHour MELLAN ’01/01/2010 00:00:00.000′ OCH ’01/02/2010 00:00:00.000′ . Hur vet vi det?

DATUMET ÄR FAKTISKT EN STRÄNG

Det stämmer.

Datumvärdena inom enstaka citattecken är egentligen inte datum utan strängar . SQL Server använder implicit konvertering för att konvertera strängen till DATETIME. Efter konverteringen kommer tidsdelen att läggas till datumet.

Låt oss inspektera med Inkludera faktisk utförandeplan . Tryck på Ctrl-M i SQL Server Management Studio, kör sedan om föregående exempel.

När exekveringsplanen visas högerklickar du på Indexsökning operatorn och välj Egenskaper . Se figur 2.

Figur 2 . Implicit konvertering av en sträng till DATETIME. Den är gömd i exekveringsplanen för en fråga som använder BETWEEN.

Expandera sedan Seek Predicates . De inrutade delarna av figur 2 visar den implicita omvandlingen av de två strängarna till DATETIME. Eftersom implicit konvertering görs internt , nybörjare blir förvirrade varför deras förväntningar i resultatuppsättningen inte uppfylls.

KORREKT ANVÄNDNING

Exemplet nedan kommer att returnera timposterna mellan 08:00 och 12:00 den 2 januari 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 måste ange tidsdelen, särskilt när datumen är desamma. Eller så kommer dina förväntade resultat inte att hända.

Om du vill returnera posterna för hela dagen fungerar det inte:


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


Det kommer bara att returnera 1 post – den för 1 juni 2010, kl. 12:00. Men genom att använda BETWEEN med de angivna tiderna kan du returnera varje timmes rekord för hela dagen. Se nästa exempel.


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;


Observera att jag endast angav fram till 23:00. Om din data används någon tid på dygnet, använd 23:59 eller 23:59 i det högre värdet i intervallet. Ange även sekunderna om du behöver det.

Tips #2:Tänk på datatypen DATUM

Om du inte behöver tidsdelen, överväg datatypen DATE istället. Och du kommer att undvika problemen som nämns ovan.

SQL MELLAN med siffror

Låt oss gå vidare till siffror.

Tips #3:Inkludera decimaldelen för icke-heltalsvärden


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;


Notera tillägget av ett annat villkor som involverar siffror. Resultaten kommer vidare att begränsas till 5 och 7 grader.

När du använder datatyperna DECIMAL, MONEY eller FLOAT, ange decimaldelen även om den är noll, som 52,00 eller 10,0000. På detta sätt undviker du implicit konvertering till måldatatyperna DECIMAL, MONEY eller FLOAT.

SQL MELLAN med strängar

Tips #4:För strängar är intervallet baserat på sortering

Med strängar utvärderar BETWEEN värden baserat på alfabetisk ordning. 'A' är minst och 'Z' är störst. Man kan också säga att i allmänhet är utvärdering baserad på sammanställning. Eftersom engelska inte är det enda språket som SQL Server stöder. Sortering ger sorteringsregler, skiftläge och accentkänslighet. Låt oss använda AdventureWorks databas för detta exempel. Kolla in koden nedan och 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 . Resultatuppsättning av en fråga som använder BETWEEN med strängar.

Området täcker efternamnet Spanaway . Men var är Splane ? Det finns inte i databasen. Så resultatet nådde bara upp till Spicer .

SQL MELLAN Tips för alla datatyper som stöds

Oavsett om du använder BETWEEN för datum, siffror eller strängar, finns det vanliga saker du bör vara medveten om. Detta kan vara sunt förnuft, men det händer ändå av misstag. Läs om hur detta kan hända.

Tips #5:Både start- och slutvärden kan inte vara NULL

BETWEEN behöver start- och slutvärden för intervallet. Var och en ska ha ett värde som inte är NULL. Det finns ett exempel med ett NULL-slutvärde nedan.


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


Detta kan hända om du anropar SELECT-satsen från en app eller en lagrad procedur och du inte validerade den ordentligt.

Tips #6:Startvärdet kan inte vara högre än slutvärdet

Ingenting kommer också att returneras om båda värdena inte är NULL, men intervallet är omvänt. Här är ett exempel.

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


Bortsett från datum kommer följande uttryck inte heller att returnera ett resultat:

  • värde MELLAN 100 OCH -200. Eftersom -200 är lägre än 100.
  • arbeta MELLAN 'Zookeeper' OCH 'Revisor'. Eftersom 'Z' är större än 'A'.

Tips #7:Områdesvärden bör vara samma datatyper

Ibland har användargränssnittskontroller oväntade resultat. Eller så har vi bara hämtat fel egendom. Och om vi inte kontrollerar det innan vi skickar det till SQL Server, kan en situation som denna inträffa:


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;

Ett konverteringsfel från en teckensträng till ett datum kommer att inträffa.

Så, lärdomen från tips #5 till #7 är att validera start- och slutvärdena för intervallet .

Tips #8:Använd INTE MELLAN för att utesluta värden

Tänk på ett annat exempel.


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


Detta kommer att returnera månadsgenomsnittet från januari till juni men exkluderar maj. Att exkludera posterna för maj 2010 är möjliggjort av NOT BETWEEN. Här är resultatet i figur 4.

Figur 4 . Resultatuppsättning av en fråga som använder NOT BETWEEN.

SQL MELLAN Jämfört med andra operatörer

Tips #9:Använd IN om du behöver en lista och inte ett intervall

IN-operatorn bestämmer om ett värde matchar något värde i en lista eller underfråga. Samtidigt kontrollerar du att använda NOT IN om ett värde inte matchar.

Operatörerna BETWEEN och IN filtrerar data baserat på flera värden. Men skillnaden ligger i uppsättningen av värden som matchas. BETTWEEN använder ett intervall. Men IN använder kommaseparerade värden i en lista eller rader i en underfråga.

Kontrollera exemplet nedan.

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;


Titta på listan över värden som används av IN. Det behöver inte vara en lista med ökande värden. Det sista värdet i listan (3.7) är också det minsta bland siffrorna.

Tips #10:Välj mellan BETWEEN eller>=med <=

Vid körning konverterar SQL Server BETWEEN till>=med <=operatorer. Hur vet vi det?

Titta på koden nedan.


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;


Båda frågorna kommer att ha samma resultatuppsättning som den i figur 5.

Figur 5 . Resultatet har angetts med antingen BETWEEN eller>=med <=.

De har också samma utförandeplan, som ses i figur 6.

Figur 6 . Exekveringsplan med 2 frågor som jämför användningen av BETWEEN, och>=och <=operatorer.

Men här är grejen.

Lägg märke till det första indexet Sök operatorn i figur 6. Se sedan Sök predikat . Ser du nyckelordet BETWEEN? Det finns ingen, eller hur? Eftersom den konverteras till>=med <=operatorer. Det är de operatorer som finns i Seek Predicates .

Men det finns mer.

Om du för musen till den andra indexsökningen operatorn kommer du att se samma egenskaper som den första indexsökningen .

Så det verkar som om operatorn BETWEEN är en genväg till>=med <=operatorer . Du kommer att skriva mer om du använder det senare. Du kommer att se samma omvandling ske när BETWEEN används i siffror och strängar.

I slutändan är det upp till dig om du använder BETWEEN eller>=och <=operatorerna. Konverteringstiden det tar att konvertera BETWEEN är försumbar. Men om du fortfarande inte vill ha den extra, försumbara tiden, använd>=och <=operatorer.

Bottomline

SQL BETWEEN är bra för att hämta data inklusive intervallet. Och det är inte så svårt att använda. Även DATETIME-värdena är hanterbara med BETWEEN. Se bara till att täcka tidsdelen ordentligt. Det motsvarar också att använda>=med <=. Det är upp till dig vilken du föredrar att använda.

Du kan bokmärka den här sidan för att få SQL BETWEEN-tips för datum, siffror och strängar när du behöver dem.

Om du har några knep med BETWEEN som vi inte täckte, kan du dela dem med oss ​​i kommentarsektionen. Och om du gillar den här artikeln, vänligen dela den genom att trycka på knapparna för sociala medier.

Lycka till med kodningen, alla!


  1. Psychopg2-bilden hittades inte

  2. Välja data från två olika servrar i SQL Server

  3. Få närmaste longitud och latitud från MSSQL-databastabellen?

  4. Hur man använder IF/ELSE-satsen för att uppdatera eller skapa ny xml-nodpost i Sql