Úvod
Chcete-li pracovat s daty v databázi, musíte být schopni efektivně získávat a cílit konkrétní záznamy. Pomocí filtrovacích klauzulí ve svých dotazech můžete přidat konkrétní kritéria, abyste vrátili pouze ty nejrelevantnější záznamy.
V této příručce se podíváme na některé z nejběžnějších operací filtrování dostupných v PostgreSQL a předvedeme, jak je použít k zúžení zaměření vašich příkazů. Ukážeme si, jak testovat proti charakteristikám v rámci jednotlivých záznamů pomocí WHERE
klauzule, jak seskupit záznamy dohromady pro shrnutí informací pomocí GROUP BY
, jak filtrovat skupiny záznamů pomocí HAVING
klauzule a jak nastavit maximální počet vrácených řádků pomocí LIMIT
doložka.
Pomocí WHERE
klauzule k definování kritérií shody
Jedním z nejběžnějších a obecně užitečných způsobů, jak uvést požadavky na dotaz, je WHERE
doložka. WHERE
klauzule umožňuje definovat skutečná kritéria vyhledávání pro příkazy dotazu zadáním podmínek, které musí být pravdivé pro všechny odpovídající záznamy.
WHERE
klauzule fungují tak, že definují booleovské výrazy, které se kontrolují proti každému kandidátnímu řádku dat. Pokud je výsledek výrazu nepravdivý, řádek bude z výsledků odstraněn a nebude vrácen ani nebude pokračovat do další fáze zpracování. Pokud je výsledek výrazu pravdivý, splňuje kritéria vyhledávání a bude pokračovat dalším zpracováním jako kandidátní řádek.
Základní syntaxe WHERE
klauzule vypadá takto:
SELECT * FROM my_table WHERE <condition>;
<condition>
může být cokoliv, co má za následek booleovskou hodnotu. V PostgreSQL je booleovská hodnota jakákoli z TRUE
, FALSE
, nebo NULL
.
Podmínky jsou často tvořeny pomocí jednoho nebo více následujících operátorů:
=
:rovno>
:větší než<
:méně než>=
:větší nebo rovno<=
:menší nebo rovno<>
nebo!=
:nerovná seAND
:logický operátor "and" — spojí dvě podmínky a vrátíTRUE
pokud jsou obě podmínkyTRUE
OR
:logický operátor "nebo" — spojí dvě podmínky a vrátíTRUE
pokud je alespoň jedna z podmínekTRUE
IN
:hodnota je obsažena v seznamu, řadě nebo rozsahu, který následujeBETWEEN
:hodnota je obsažena v rozsahu minimálních a maximálních hodnot, které následují, včetněIS NULL
:odpovídá, pokud je hodnotaNULL
NOT
:neguje logickou hodnotu, která následujeEXISTS
:následující dotaz obsahuje výsledkyILIKE
:odpovídá vzoru (pomocí zástupných znaků%
aby odpovídalo 0 nebo více znakům a_
aby odpovídal jednomu znaku)ILIKE
:odpovídá vzoru (pomocí zástupných znaků%
aby odpovídalo 0 nebo více znakům a_
pro shodu s jedním znakem), nerozlišují se malá a velká písmenaSIMILAR TO
:odpovídá vzoru pomocí dialektu regulárních výrazů SQL~
:odpovídá vzoru pomocí regulárních výrazů POSIX, rozlišují se malá a velká písmena~*
:odpovídá vzoru pomocí regulárních výrazů POSIX, nerozlišují se malá a velká písmena!~
:neodpovídá vzoru používajícímu regulární výrazy POSIX, rozlišují se malá a velká písmena!~*
:neodpovídá vzoru používajícímu regulární výrazy POSIX, nerozlišují se malá a velká písmena
Zatímco výše uvedený seznam představuje některé z nejběžnějších testovacích konstrukcí, existuje mnoho dalších operátorů, které poskytují booleovské výsledky, které lze použít ve spojení s WHERE
doložka.
Příklady pomocí WHERE
Jednou z nejběžnějších a nejpřímějších kontrol je rovnost pomocí =
operátor. Zde zkontrolujeme, zda každý řádek v customer
tabulka má last_name
hodnota se rovná Smith
:
SELECT * FROM customer WHERE last_name = 'Smith';
K tomu můžeme přidat další podmínky pro vytváření složených výrazů pomocí logických operátorů. Tento příklad používá AND
klauzule pro přidání dalšího testu proti first_name
sloupec. Platné řádky musí splňovat obě uvedené podmínky:
SELECT * FROM customer WHERE first_name = 'John' AND last_name = 'Smith';
Podobně můžeme zkontrolovat, zda je splněna některá z řady podmínek. Zde kontrolujeme řádky z address
tabulka, abyste viděli, zda zip_code
hodnota je rovna 60626 nebo neighborhood
sloupec se rovná řetězci "Roger's Park". Používáme dvě jednoduché uvozovky k označení, že by se měla hledat doslovná jednoduchá uvozovka:
SELECT * FROM address WHERE zip_code = '60626' OR neighborhood = 'Roger''s Park';
IN
operátor může fungovat jako srovnání mezi řadou hodnot, zabalených v závorkách. Pokud existuje shoda s některou z uvedených hodnot, výraz je TRUE
:
SELECT * FROM customer WHERE last_name IN ('Smith', 'Johnson', 'Fredrich');
Zde porovnáváme vzor řetězce pomocí ILIKE
. %
funguje jako zástupný znak odpovídající nule nebo více znakům, takže „Pete“, „Peter“ a jakýkoli jiný řetězec začínající „Pete“ by odpovídal:
SELECT * FROM customer WHERE last_name LIKE 'Pete%';
Mohli bychom provést podobné vyhledávání pomocí ~*
operátor pro kontrolu shody pomocí regulárních výrazů POSIX bez ohledu na velikost písmen. V tomto případě zkontrolujeme, zda je hodnota last_name
začíná na „d“ a obsahuje podřetězec „on“, který by odpovídal jménům jako „Dickson“, „Donald“ a „Devon“:
SELECT * FROM customer WHERE last_name ~* '^D.*on.*';
Můžeme zkontrolovat, zda se číslo ulice nachází v bloku 4000 adres pomocí BETWEEN
a AND
operátory k definování inkluzivního rozsahu:
SELECT * FROM address WHERE street_number BETWEEN 4000 AND 4999;
Zde můžeme zobrazit libovolného customer
položky, které mají čísla sociálního zabezpečení, která nejsou dlouhá 9 číslic. Používáme LENGTH()
operátor pro získání počtu číslic v poli a <>
pro kontrolu nerovnosti:
SELECT * FROM customer WHERE LENGTH(SSN) <> 9;
Použití GROUP BY
klauzule pro shrnutí více záznamů
GROUP BY
klauzule je dalším velmi běžným způsobem filtrování výsledků reprezentováním více výsledků na jednom řádku. Základní syntaxe GROUP BY
klauzule vypadá takto:
SELECT <columns> FROM some_table GROUP BY <columns_to_group>
Když GROUP BY
klauzule přidána do příkazu, říká PostgreSQL, aby zobrazil jeden řádek pro každou jedinečnou hodnotu pro daný sloupec nebo sloupce. To má některé důležité důsledky.
Protože GROUP BY
klauzule je způsob reprezentace více řádků jako jeden řádek, PostgreSQL může provést dotaz pouze tehdy, pokud dokáže vypočítat hodnotu pro každý ze sloupců, který má za úkol zobrazit. To znamená, že každý sloupec identifikován pomocí SELECT
část příkazu musí být buď:
- zahrnuto do
GROUP BY
klauzule, která zaručí, že každý řádek má jedinečnou hodnotu - abstrakce pro shrnutí všech řádků v každé skupině
Prakticky to znamená, že všechny sloupce v SELECT
seznam není součástí GROUP BY
klauzule musí používat agregační funkci k vytvoření jediného výsledku pro sloupec pro každou skupinu.
Příklady pomocí GROUP BY
Pro příklady v této sekci předpokládejme, že máme tabulku nazvanou pet
které jsme definovali a naplnili takto:
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);
Nejjednodušší použití GROUP BY
je zobrazení rozsahu jedinečných hodnot pro jeden sloupec. Chcete-li tak učinit, použijte stejný sloupec v SELECT
a GROUP BY
. Zde vidíme všechny barvy použité v tabulce:
SELECT color FROM pet GROUP BY color;
color-------- black grey brown white orange(5 rows)
Když se přesunete za jeden sloupec v SELECT
sloupce, musíte buď přidat sloupce do GROUP BY
klauzuli nebo použijte agregační funkci k vytvoření jediné hodnoty pro skupinu reprezentovaných řádků.
Zde přidáme type
do GROUP BY
klauzule, což znamená, že každý řádek bude představovat jedinečnou kombinaci type
a color
hodnoty. Přidáme také age
sloupec shrnutý pomocí avg()
funkce pro zjištění průměrného věku každé ze skupin:
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)
Agregační funkce fungují stejně dobře s jedním sloupcem v GROUP BY
doložka. Zde najdeme průměrný věk každého druhu zvířat:
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)
Pokud chceme zobrazit nejstarší z každého druhu zvířat, mohli bychom místo toho použít max()
funkce na age
sloupec. GROUP BY
klauzule sbalí výsledky do stejných řádků jako dříve, ale nová funkce změní výsledek v druhém sloupci:
SELECT type, max(age) AS oldest FROM pet GROUP BY type;
type | oldest--------+------- rabbit | 8 dog | 7 cat | 8(3 rows)
Pomocí HAVING
klauzule k filtrování skupin záznamů
GROUP BY
klauzule je způsob, jak shrnout data sbalením více záznamů do jednoho reprezentativního řádku. Ale co když chcete tyto skupiny zúžit na základě dalších faktorů?
HAVING
klauzule je modifikátor pro GROUP BY
klauzule, která vám umožní specifikovat podmínky, které musí každá skupina splnit, aby byla zahrnuta do výsledků.
Obecná syntaxe vypadá takto:
SELECT <columns> FROM some_table GROUP BY <columns_to_group> HAVING <condition>
Operace je velmi podobná WHERE
klauzule, s tím rozdílem, že WHERE
filtruje jednotlivé záznamy a HAVING
filtruje skupiny záznamů.
Příklady pomocí HAVING
Pomocí stejné tabulky, kterou jsme představili v minulé sekci, můžeme demonstrovat, jak HAVING
doložka funguje.
Zde seskupujeme řádky pet
tabulky podle jedinečných hodnot v type
a najděte minimální hodnotu age
také. HAVING
klauzule pak filtruje výsledky, aby odstranil všechny skupiny, kde věk není větší než 1:
SELECT type, min(age) AS youngest FROM pet GROUP BY type HAVING min(age) > 1;
type | youngest--------+---------- rabbit | 4 cat | 4(2 rows)
V tomto příkladu seskupujeme řádky do pet
podle jejich barvy. Potom filtrujeme skupiny, které představují pouze jeden řádek. Výsledek nám ukáže každou barvu, která se objeví více než jednou:
SELECT color FROM pet GROUP BY color HAVING count(color) > 1;
color------- black brown(2 rows)
Můžeme provést podobný dotaz, abychom získali kombinace type
a color
že pouze jedno zvíře má:
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)
Použití LIMIT
klauzule pro nastavení maximálního počtu záznamů
LIMIT
klauzule nabízí jiný přístup k ořezávání záznamů, které váš dotaz vrátí. Spíše než odstranění řádků dat na základě kritérií v rámci samotného řádku, LIMIT
klauzule nastavuje maximální počet záznamů vrácených dotazem.
Základní syntaxe LIMIT
vypadá takto:
SELECT * FROM my_table LIMIT <num_rows> [OFFSET <num_rows_to_skip>];
Zde <num_rows>
označuje maximální počet řádků k zobrazení z provedeného dotazu. Toto se často používá ve spojení s ORDER BY
klauzule k získání řádků s nejextrémnějšími hodnotami v určitém sloupci. Chcete-li například získat pět nejlepších skóre u zkoušky, může uživatel ORDER BY
score
a poté LIMIT
výsledky do 5.
Zatímco LIMIT
ve výchozím nastavení se počítá od začátku výsledků, volitelný OFFSET
klíčové slovo lze použít ke kompenzaci výchozí pozice, kterou používá. Ve skutečnosti vám to umožňuje stránkovat výsledky zobrazením počtu výsledků definovaných LIMIT
a poté přidání LIMIT
číslo do OFFSET
k načtení následující stránky.
Příklady pomocí LIMIT
Použijeme pet
pro příklady v této sekci.
Jak je uvedeno výše, LIMIT
se často kombinuje s ORDER BY
klauzule k explicitnímu definování pořadí řádků před rozdělením příslušného počtu. Zde třídíme pet
položky podle jejich age
, od nejstarších po nejmladší. Potom použijeme LIMIT
pro zobrazení 5 nejstarších zvířat:
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)
Bez ORDER BY
klauzule, LIMIT
provede výběr zcela předvídatelným způsobem. Vrácené výsledky mohou být ovlivněny pořadím položek v tabulce nebo indexy. To není vždy špatná věc.
Pokud potřebujeme záznam pro jakéhokoli jednotlivého dog
v tabulce bychom mohli vytvořit dotaz takto. Mějte na paměti, že ačkoli může být obtížné předvídat výsledek, nejedná se o náhodný výběr a neměl by být jako takový používán:
SELECT * FROM pet WHERE type = 'dog' LIMIT 1;
type | name | color | age | id------+------+-------+-----+---- dog | Spot | brown | 3 | 1(1 row)
Můžeme použít OFFSET
klauzule pro stránkování výsledků. Zahrnujeme ORDER BY
klauzule k definování konkrétního pořadí výsledků.
U prvního dotazu omezíme výsledky bez zadání OFFSET
získat první 3 nejmladší příspěvky:
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)
Abychom získali další 3 nejmladší, můžeme přidat číslo definované v LIMIT
na OFFSET
přeskočit výsledky, které jsme již získali:
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)
Pokud přidáme LIMIT
na OFFSET
opět získáme další 3 výsledky:
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)
To nám umožňuje načíst řádky dat z dotazu ve spravovatelných blocích.
Závěr
Existuje mnoho způsobů, jak filtrovat a jinak omezit výsledky, které získáte z dotazů. Klauzule jako WHERE
a HAVING
vyhodnotit potenciální řádky nebo skupiny řádků a zjistit, zda splňují určitá kritéria. GROUP BY
klauzule vám pomůže shrnout data seskupením záznamů, které mají jednu nebo více hodnot sloupců společných. LIMIT
klauzule nabízí uživatelům možnost nastavit pevné maximum počtu záznamů k načtení.
Naučte se, jak lze tyto klauzule aplikovat, jednotlivě nebo v kombinaci, vám umožní extrahovat konkrétní data z velkých datových sad. Modifikátory dotazů a filtry jsou nezbytné pro přeměnu dat, která žijí v PostgreSQL, na užitečné odpovědi.