Introduktion
För att arbeta med data i en databas måste du kunna hämta och rikta in specifika poster effektivt. Genom att använda filtreringssatser i dina frågor kan du lägga till specifika kriterier för att endast returnera de mest relevanta posterna.
I den här guiden kommer vi att ta en titt på några av de vanligaste filtreringsoperationerna som finns tillgängliga inom PostgreSQL och visa hur man använder dem för att begränsa fokus för dina uttalanden. Vi kommer att visa hur man testar mot egenskaper inom individuella poster med WHERE
satser, hur man grupperar poster för att sammanfatta information med GROUP BY
, hur man filtrerar grupper av poster med HAVING
underklausul och hur man ställer in det maximala antalet returnerade rader med LIMIT
klausul.
Använda WHERE
sats för att definiera matchningskriterier
Ett av de vanligaste och allmänt användbara sätten att ange dina frågekrav är WHERE
klausul. WHERE
sats låter dig definiera faktiska sökkriterier för frågesatser genom att ange villkor som måste vara sanna för alla matchande poster.
VAR
satser fungerar genom att definiera booleska uttryck som kontrolleras mot varje kandidatrad med data. Om resultatet av uttrycket är falskt kommer raden att tas bort från resultaten och kommer inte att returneras eller fortsätta till nästa steg av bearbetningen. Om resultatet av uttrycket är sant, uppfyller det kriterierna för sökningen och kommer att fortsätta för ytterligare bearbetning som en kandidatrad.
Den grundläggande syntaxen för WHERE
klausul ser ut så här:
SELECT * FROM my_table WHERE <condition>;
kan vara vad som helst som resulterar i ett booleskt värde. I PostgreSQL är ett booleskt värde något av TRUE
, FALSKT
, eller NULL
.
Villkor skapas ofta med en eller flera av följande operatorer:
=
:lika med>
:större än<
:mindre än>=
:större än eller lika med<=
:mindre än eller lika med<> eller
!=
:inte likaOCH
:den logiska "och"-operatorn — förenar två villkor och returnerarTRUE
om båda villkoren ärTRUE
ELLER
:logisk "eller"-operator — sammanfogar två villkor och returnerarTRUE
om minst ett av villkoren ärTRUE
IN
:värdet finns i listan, serien eller intervallet som följerMELLAN
:värde finns inom intervallet de lägsta och högsta värdena som följer, inklusiveÄR NULL
:matchar om värdet ärNULL
INTE
:negerar det booleska värdet som följerFINNS
:frågan som följer innehåller resultatGILLA
:matchar mot ett mönster (med jokertecken%
för att matcha 0 eller fler tecken och__
för att matcha ett enstaka tecken)ILIKE
:matchar mot ett mönster (med jokertecken%
för att matcha 0 eller fler tecken och__
för att matcha ett enstaka tecken), skiftlägesokänsligLIKER MED
:matchar mot ett mönster med SQLs dialekt för reguljära uttryck~
:matchar mot ett mönster med POSIX reguljära uttryck, skiftlägeskänsliga~*
:matchar mot ett mönster med POSIX reguljära uttryck, skiftlägesokänslig!~
:matchar inte mot ett mönster som använder POSIX reguljära uttryck, skiftlägeskänsliga!~*
:matchar inte mot ett mönster som använder POSIX reguljära uttryck, skiftlägesokänslig
Även om listan ovan representerar några av de vanligaste testkonstruktionerna, finns det många andra operatorer som ger booleska resultat som kan användas tillsammans med en WHERE
klausul.
Exempel som använder WHERE
En av de vanligaste och enklaste kontrollerna är för jämlikhet, med hjälp av =
operatör. Här kontrollerar vi om varje rad i kunden
tabellen har ett efternamn
värde lika med Smith
:
SELECT * FROM customer WHERE last_name = 'Smith';
Vi kan lägga till ytterligare villkor för att skapa sammansatta uttryck med logiska operatorer. Det här exemplet använder AND
sats för att lägga till ett ytterligare test mot first_name
kolumn. Giltiga rader måste uppfylla båda de angivna villkoren:
SELECT * FROM customer WHERE first_name = 'John' AND last_name = 'Smith';
På samma sätt kan vi kontrollera om något av en rad villkor är uppfyllda. Här kontrollerar vi rader från adressen
tabell för att se om zip_code
värdet är lika med 60626 eller grannskapet
kolumn är lika med strängen "Rogers Park". Vi använder två enkla citattecken för att indikera att ett bokstavligt enstaka citattecken ska sökas efter:
SELECT * FROM address WHERE zip_code = '60626' OR neighborhood = 'Roger''s Park';
IN
operatorn kan fungera som en jämförelse mellan ett antal värden, inslagna inom parentes. Om det finns en matchning med något av de givna värdena är uttrycket TRUE
:
SELECT * FROM customer WHERE last_name IN ('Smith', 'Johnson', 'Fredrich');
Här kontrollerar vi mot ett strängmönster med LIKE
. %
fungerar som ett jokertecken som matchar noll eller fler tecken, så "Pete", "Peter" och alla andra strängar som börjar med "Pete" skulle matcha:
SELECT * FROM customer WHERE last_name LIKE 'Pete%';
Vi skulle kunna göra en liknande sökning med ~*
operatorn för att söka efter matchningar med POSIX reguljära uttryck utan hänsyn till skiftläge. I det här fallet kontrollerar vi om värdet för last_name
börjar med ett "d" och innehåller delsträngen "on", som skulle matcha namn som "Dickson", "Donald" och "Devon":
SELECT * FROM customer WHERE last_name ~* '^D.*on.*';
Vi kan kontrollera om ett gatunummer finns inom 4000-blocket med adresser med hjälp av BETWEEN
och OCH
operatörer för att definiera ett inkluderande intervall:
SELECT * FROM address WHERE street_number BETWEEN 4000 AND 4999;
Här kan vi visa vilken kund
som helst poster som har personnummer som inte är 9 siffror långa. Vi använder LENGTH()
operatorn för att få antalet siffror i fältet och
SELECT * FROM customer WHERE LENGTH(SSN) <> 9;
Använda GROUP BY
klausul för att sammanfatta flera poster
GROUP BY
klausul är ett annat mycket vanligt sätt att filtrera resultat genom att representera flera resultat med en enda rad. Den grundläggande syntaxen för GROUP BY
klausul ser ut så här:
SELECT <columns> FROM some_table GROUP BY <columns_to_group>
När en GROUP BY
sats läggs till i en sats, säger den till PostgreSQL att visa en enda rad för varje unikt värde för den givna kolumnen eller kolumnerna. Detta har några viktiga konsekvenser.
Sedan GROUP BY
sats är ett sätt att representera flera rader som en enda rad, PostgreSQL kan bara exekvera frågan om den kan beräkna ett värde för var och en av kolumnerna som den har till uppgift att visa. Detta innebär att varje kolumn identifieras av SELECT
del av uttalandet måste antingen vara:
- ingår i
GROUP BY
klausul för att garantera att varje rad har ett unikt värde - abstrakt för att sammanfatta alla rader inom varje grupp
Praktiskt sett betyder det att alla kolumner i SELECT
listan ingår inte i GROUP BY
sats måste använda en aggregatfunktion för att producera ett enda resultat för kolumnen för varje grupp.
Exempel som använder GROUP BY
För exemplen i det här avsnittet, anta att vi har en tabell som heter pet
som vi har definierat och fyllt i så här:
CREATE TABLE pet ( id SERIAL PRIMARY KEY, type TEXT, name TEXT, color TEXT, age INT);INSERT INTO pet (type, name, color, age) VALUES('dog', 'Spot', 'brown', 3),('dog', 'Rover', 'black', 7),('dog', 'Sally', 'brown', 1),('cat', 'Sabrina', 'black', 8),('cat', 'Felix', 'white', 4),('cat', 'Simon', 'orange', 8),('rabbit', 'Buttons', 'grey', 4),('rabbit', 'Bunny', 'brown', 8),('rabbit', 'Briony', 'brown', 6);
Den enklaste användningen av GROUP BY
är att visa intervallet av unika värden för en enskild kolumn. För att göra det, använd samma kolumn i SELECT
och GROUP BY
. Här ser vi alla färger som används i tabellen:
SELECT color FROM pet GROUP BY color;
color-------- black grey brown white orange(5 rows)
När du går bortom en enskild kolumn i SELECT
kolumnlistan måste du antingen lägga till kolumnerna i GROUP BY
sats eller använd en aggregatfunktion för att skapa ett enda värde för gruppen av rader som representeras.
Här lägger vi till typ
till GROUP BY
sats, vilket betyder att varje rad kommer att representera en unik kombination av typ
och färg
värden. Vi lägger också till ålder
kolumn, sammanfattad med avg()
funktion för att hitta medelåldern för var och en av grupperna:
SELECT type, color, avg(age) AS average_age FROM pet GROUP BY type, color;
type | color | average_age--------+--------+-------------------- rabbit | brown | 7.0000000000000000 cat | black | 8.0000000000000000 rabbit | grey | 4.0000000000000000 dog | black | 7.0000000000000000 dog | brown | 2.0000000000000000 cat | orange | 8.0000000000000000 cat | white | 4.0000000000000000(7 rows)
Aggregatfunktioner fungerar lika bra med en enda kolumn i GROUP BY
klausul. Här hittar vi medelåldern för varje typ av djur:
SELECT type, avg(age) AS average_age FROM PET GROUP BY type;
type | average_age--------+-------------------- rabbit | 6.0000000000000000 dog | 3.6666666666666667 cat | 6.6666666666666667(3 rows)
Om vi vill visa den äldsta av varje typ av djur kan vi istället använda max()
funktion på ålder
kolumn. GROUP BY
sats komprimerar resultaten i samma rader som tidigare, men den nya funktionen ändrar resultatet i den andra kolumnen:
SELECT type, max(age) AS oldest FROM pet GROUP BY type;
type | oldest--------+------- rabbit | 8 dog | 7 cat | 8(3 rows)
Använda HAVING
sats för att filtrera grupper av poster
GROUP BY
klausul är ett sätt att sammanfatta data genom att komprimera flera poster till en enda representativ rad. Men vad händer om du vill begränsa dessa grupper baserat på ytterligare faktorer?
HAVING
satsen är en modifierare för GROUP BY
klausul som låter dig specificera villkor som varje grupp måste uppfylla för att inkluderas i resultaten.
Den allmänna syntaxen ser ut så här:
SELECT <columns> FROM some_table GROUP BY <columns_to_group> HAVING <condition>
Operationen är mycket lik WHERE
klausul, med skillnaden att WHERE
filtrerar enskilda poster och HAVING
filtrerar grupper av poster.
Exempel som använder HAVING
Med samma tabell som vi introducerade i det förra avsnittet kan vi visa hur HAVING
klausul fungerar.
Här grupperar vi raderna för husdjuret
tabell efter unika värden i type
kolumnen, hitta minimivärdet för ålder
också. HAVING
klausul filtrerar sedan resultaten för att ta bort alla grupper där åldern inte är högre än 1:
SELECT type, min(age) AS youngest FROM pet GROUP BY type HAVING min(age) > 1;
type | youngest--------+---------- rabbit | 4 cat | 4(2 rows)
I det här exemplet grupperar vi raderna i pet
efter deras färg. Vi filtrerar sedan de grupper som bara representerar en enda rad. Resultatet visar oss varje färg som visas mer än en gång:
SELECT color FROM pet GROUP BY color HAVING count(color) > 1;
color------- black brown(2 rows)
Vi kan utföra en liknande fråga för att få kombinationerna av typ
och färg
att endast ett enda djur har:
SELECT type, color FROM pet GROUP BY type, color HAVING count(color) = 1;
type | color--------+-------- cat | black rabbit | grey dog | black cat | orange cat | white(5 rows)
Använda LIMIT
sats för att ställa in det maximala antalet poster
LIMIT
klausulen erbjuder ett annat tillvägagångssätt för att minska de poster som din fråga returnerar. Istället för att eliminera rader med data baserat på kriterier inom själva raden, är LIMIT
sats anger det maximala antalet poster som returneras av en fråga.
Den grundläggande syntaxen för LIMIT
ser ut så här:
SELECT * FROM my_table LIMIT <num_rows> [OFFSET <num_rows_to_skip>];
Här är
anger det maximala antalet rader som ska visas från den körda frågan. Detta används ofta tillsammans med ORDER BY
satser för att få raderna med de mest extrema värdena i en viss kolumn. Till exempel, för att få de fem bästa poängen på ett prov kan en användare ORDER BY
en poäng
kolumn och sedan LIMIT
resultaten till 5.
Medan LIMIT
räknas från toppen av resultaten som standard, den valfria OFFSET
nyckelordet kan användas för att förskjuta startpositionen den använder. I själva verket låter detta dig sidställa genom resultat genom att visa antalet resultat som definieras av LIMIT
och lägg sedan till LIMIT
nummer till OFFSET
för att hämta följande sida.
Exempel som använder LIMIT
Vi kommer att använda pet
tabell från tidigare för exemplen i detta avsnitt.
Som nämnts ovan, LIMIT
kombineras ofta med en ORDER BY
klausul för att uttryckligen definiera ordningen för raderna innan du delar upp det lämpliga numret. Här sorterar vi husdjuret
poster enligt deras ålder
, från äldst till yngst. Vi använder sedan LIMIT
för att visa de 5 äldsta djuren:
SELECT * FROM pet ORDER BY age DESC LIMIT 5;
type | name | color | age | id--------+---------+--------+-----+---- cat | Simon | orange | 8 | 6 cat | Sabrina | black | 8 | 4 rabbit | Bunny | brown | 8 | 8 dog | Rover | black | 7 | 2 rabbit | Briany | brown | 6 | 9(5 rows)
Utan en ORDER BY
klausul, LIMIT
kommer att göra urval på ett helt förutsägbart sätt. Resultaten som returneras kan påverkas av ordningen på posterna i tabellen eller av index. Detta är inte alltid en dålig sak.
Om vi behöver en post för någon enskild hund
i tabellen kan vi konstruera en fråga som denna. Tänk på att även om resultatet kan vara svårt att förutsäga, är detta inte ett slumpmässigt urval och bör inte användas som sådant:
SELECT * FROM pet WHERE type = 'dog' LIMIT 1;
type | name | color | age | id------+------+-------+-----+---- dog | Spot | brown | 3 | 1(1 row)
Vi kan använda OFFSET
klausul för att paginera genom resultat. Vi inkluderar en ORDER BY
klausul för att definiera en specifik ordning för resultaten.
För den första frågan begränsar vi resultaten utan att ange en OFFSET
för att få de tre första yngsta bidragen:
SELECT * FROM pet ORDER BY age LIMIT 3;
type | name | color | age | id------+-------+-------+-----+---- dog | Sally | brown | 1 | 3 dog | Spot | brown | 3 | 1 cat | Felix | white | 4 | 5(3 rows)
För att få nästa 3 yngsta kan vi lägga till numret som definieras i LIMIT
till OFFSET
för att hoppa över resultaten vi redan har hämtat:
SELECT * FROM pet ORDER BY age LIMIT 3 OFFSET 3;
type | name | color | age | id --------+---------+-------+-----+---- rabbit | Buttons | grey | 4 | 7 rabbit | Briany | brown | 6 | 9 dog | Rover | black | 7 | 2(3 rows)
Om vi lägger till LIMIT
till OFFSET
igen, vi får de kommande 3 resultaten:
SELECT * FROM pet ORDER BY age LIMIT 3 OFFSET 6;
type | name | color | age | id--------+---------+--------+-----+---- cat | Simon | orange | 8 | 6 rabbit | Bunny | brown | 8 | 8 cat | Sabrina | black | 8 | 4(3 rows)
Detta låter oss hämta rader med data från en fråga i hanterbara bitar.
Slutsats
Det finns många sätt att filtrera och på annat sätt begränsa resultaten du får från frågor. Klausuler som WHERE
och HAV
utvärdera potentiella rader eller grupper av rader för att se om de uppfyller vissa kriterier. GROUP BY
sats hjälper dig att sammanfatta data genom att gruppera poster som har ett eller flera kolumnvärden gemensamma. LIMIT
klausulen ger användarna möjligheten att sätta ett hårt maximum för antalet poster som ska hämtas.
Genom att lära dig hur dessa klausuler kan tillämpas, individuellt eller i kombination, kan du extrahera specifik data från stora datamängder. Frågemodifierare och filter är viktiga för att omvandla data som finns i PostgreSQL till användbara svar.