sql >> Databáze >  >> RDS >> PostgreSQL

Moje oblíbené PostgreSQL dotazy a proč na nich záleží

Databáze, tabulky, normalizace a solidní plán zálohování nám umožňují ukládat a udržovat data.

Tyto kombinované osvědčené postupy nám zase umožňují interakci s těmito údaji. V dnešním světě založeném na datech jsou data cenná. Nejen cenná, data jsou často kritická pro řešení pro koncové uživatele poskytovaná produkty a službami. Získávání přehledu, odpovídání na otázky a smysluplné metriky z dat prostřednictvím dotazování a manipulace s daty je nedílnou součástí SQL obecně.

PostgreSQL se neliší.

Toto základní jádro je zásadní pro úspěch v jakémkoli aspektu založeném na datech.

Níže uvádím kombinaci 8 různých dotazů nebo typů dotazů, které jsem považoval za zajímavé a poutavé pro zkoumání, studium, učení nebo jinou manipulaci s datovými soubory.

Nejsou uvedeny v žádném pořadí podle důležitosti.

Většina z nich budou pravděpodobně známí staří přátelé. Možná se někteří stanou novými známými.

Použité vzorové tabulky a data nejsou tak důležité jako samotná konstrukce dotazů a toho, co každý dotaz vrací, nabízí nebo poskytuje. Mnohé z nich jsou zesměšňovány a odvozeny pro demonstrační účely a neměly by být brány doslova v jejich hodnotách.

1. Levé připojení, nuly vpravo...

Předpokládejme, že v tomto příkladu běží prodej po dobu dvou měsíců a dostáváme dohromady obojí.

Přesto z nějakého důvodu druhý měsíc nezvýšil svou váhu a my se chceme zaměřit na to, ve kterých dnech v prvním měsíci došlo k poklesu.

Tyto prodeje jsou reprezentovány jako platba za stoly a fake_month pro tuto ukázku.

Poznámka:

  • Zkontrolujeme pouze součty větší než 2 000.
  • Omezíme výstup na pouhých 10 řádků.

Pro začátek máme tento Common Table Expression (CTE) 'generování ' tabulku fake_month pro nás a dotaz, který následuje.

dvdrental=> WITH fake_month AS(
SELECT setup::date
FROM generate_series('2007-02-01', '2007-02-28', INTERVAL '1 day') AS setup
)
SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
LIMIT 10;
legit | sum | fake
-------+---------+------
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
20 | 3888.98 | 20
21 | 3786.14 | 21
(10 rows)

Vypadá to, že tam přispěly oba měsíce. Takže je to vyřešeno?

Než to budeme považovat za vyřešené, podívejme se na klauzuli ORDER BY.

Samozřejmě můžete OBJEDNAT PODLE ASC nebo DESC.

Můžete však také OBJEDNAT PO NULOVÝCH prvcích nebo posledních a to trochu mění věci.

Přepišme tento dotaz a nejprve v legitimním sloupci použijte ORDER BY NULLS.

Pro stručnost odstraním CTE z výstupu, stačí vědět, že tam stále je a že se používá.

SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
ORDER BY legit NULLS first
LIMIT 10;
legit | sum | fake
-------+---------+------
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
20 | 3888.98 | 20
21 | 3786.14 | 21
(10 rows)

Není v tom vůbec žádný rozdíl.

Co když nejprve OBJEDNAME PODLE NULL na falešném sloupci? Ten vpravo straně JOIN?

Uvidíme.

SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
ORDER BY fake NULLS first
LIMIT 10;
legit | sum | fake
-------+---------+------
29 | 2717.60 |
30 | 5723.89 |
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
(10 rows)

Teď se někam dostáváme. Vidíme, že 29. a 30. den byl falešný sloupec seřazen z horní části sady výsledků.

Kvůli ORDER BY falešným NULLS nejprve.

Tím je vyřešena naše otázka, na jaké dny „výprodej 2“ polevil.

Zajímá vás...

Můžeme filtrovat pomocí WHERE fake IS NULL? "

."

Takhle:

SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
WHERE date_part('day', fk.setup) IS NULL
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
LIMIT 10;
legit | sum | fake
-------+---------+------
29 | 2717.60 |
30 | 5723.89 |
(2 rows)

Ano, funguje to. Proč tedy místo toho nepoužít tento dotaz? Proč na tom záleží?

Mám pocit, že použití LEFT JOIN a ORDER BY NULLS jako první pro tabulku na pravé straně JOIN je skvělý způsob, jak prozkoumat neznámé tabulky a soubory dat.

Potvrzením, která data, pokud vůbec nějaká, „chybějí ’ na této straně podmínky spojení jako první; zlepšuje srozumitelnost a povědomí, což vám umožňuje odfiltrovat sadu výsledků pomocí klauzule WHERE JE NULL, čímž vše dokončíte.

Samozřejmě znalost tabulek a datových sad by mohla potenciálně eliminovat potřebu zde prezentovaného LEFT JOIN.

Je to hodný dotaz pro každého, kdo používá PostgreSQL, aby to alespoň zkusil během průzkumu.

2. Zřetězení řetězců

Zřetězení, spojení nebo připojení dvou řetězců, poskytuje možnost prezentace sad výsledků. Mnoho 'věcí ' lze zřetězit.

Jak je však uvedeno v dokumentaci, operátor zřetězení řetězců ('||') přijímá neřetězcový vstup, pokud je jeden řetězec.

Podívejme se na několik příkladů s níže uvedenými dotazy:

postgres=> SELECT 2||' times'||' 2 equals: '|| 2*2;
?column?
---------------------
2 times 2 equals: 4
(1 row)

Vidíme, že čísla a řetězce lze všechny zřetězit dohromady, jak je uvedeno výše.

'||' Operátor je pouze jedním z dostupných v PostgreSQL.

Funkce concat() přijímá více argumentů a při návratu je všechny zřetězí.

Zde je příklad této funkce v akci:

postgres=> SELECT concat('Josh ','Otwell') AS first_name;
first_name
-------------
Josh Otwell
(1 row)

V případě potřeby můžeme předat více než dva argumenty:

postgres=> SELECT concat('Josh',' ','Otwell') AS first_name;
first_name
-------------
Josh Otwell
(1 row)

Všimněme si něčeho opravdu rychlého na následujících příkladech:

postgres=> SELECT CONCAT('Josh',NULL,'Otwell') AS first_name;
first_name
------------
JoshOtwell
(1 row)
postgres=> SELECT 'Josh '||NULL||'Otwell' AS first_name;
first_name
------------
(1 row)
postgres=> SELECT NULL||'Josh '||'Otwell' AS first_name;
first_name
------------
(1 row)
postgres=> SELECT CONCAT(NULL,'Josh','Otwell') AS first_name;
first_name
------------
JoshOtwell
(1 row)

Všimněte si, že funkce concat() ignoruje hodnotu NULL bez ohledu na to, kde je v seznamu parametrů umístěna, zatímco operátor zřetězení řetězců nikoli.

Je-li kdekoli v řetězci, který se má zřetězit, je vrácena hodnota NULL.

Jen si toho uvědomte.

Místo ručního zahrnutí do řetězce, který má být zřetězen, PostgreSQL také obsahuje funkci concat_ws(), která akceptuje oddělovač řetězců jako první parametr.

Navštívíme ho s těmito dotazy:

postgres=> SELECT concat_ws('-',333,454,1919) AS cell_num;
cell_num
--------------
333-454-1919
(1 row)
postgres=> SELECT concat_ws(' ','Josh','Otwell') AS first_name;
first_name
-------------
Josh Otwell
(1 row)

concat_ws() přijímá jako argumenty buď čísla nebo řetězce a jak je uvedeno výše, používá první argument jako oddělovač.

Jak concat_ws() zachází s NULL?

postgres=> SELECT concat_ws('-',333,NULL,1919) AS cell_num;
cell_num
----------
333-1919
(1 row)
postgres=> SELECT concat_ws(NULL,333,454,1919) AS cell_num;
cell_num
----------
(1 row)

Hodnota NULL je ignorována, pokud to není argument oddělovače daný concat_ws().

Potom jsou všechny argumenty ignorovány a místo toho je vrácena hodnota NULL.

Zřetězení je skvělé...

Nyní, když máme představu o tom, jak zřetězení funguje, podívejme se na několik jeho příkladů.

Zpět do databáze simulovaných DVD půjčoven

Předpokládejme, že potřebujeme sestavit seznam jmen a příjmení zákazníků spolu s jejich e-mailovou adresou, abychom mohli odeslat zprávu o aktualizaci jejich účtu.

Kvůli stručnosti omezím výstup na pouhých 10 řádků, ale stále demonstruji || operátor.

dvdrental=> SELECT first_name||' '||last_name||'''s email address is: '||email AS name_and_email
FROM customer
LIMIT 10;
name_and_email
--------------------------------------------------------------------------
Jared Ely's email address is: [email protected]
Mary Smith's email address is: [email protected]
Patricia Johnson's email address is: [email protected]
Linda Williams's email address is: [email protected]
Barbara Jones's email address is: [email protected]
Elizabeth Brown's email address is: [email protected]
Jennifer Davis's email address is: [email protected]
Maria Miller's email address is: [email protected]
Susan Wilson's email address is: [email protected]
Margaret Moore's email address is: [email protected]
(10 rows)

Všimněte si, že jsme museli opustit jednoduchou uvozovku používanou s apostrofy a použít další jedinou uvozovku, která ukazuje vlastnictví e-mailové adresy každého zákazníka.

Proč byste to měli vědět?

Mohou nastat situace, kdy vám zřetězení dat poskytne lepší přehled a porozumění datové sadě, se kterou pracujete. Spolu s možnostmi hlášení by zřetězení sdílených datových sad s ostatními mohlo potenciálně učinit tyto (data) čitelnějšími a stravitelnějšími.

3. Dodání seznamu hodnot IN pomocí poddotazu

Poddotaz má mnoho výkonných využití. Mezi nimi je běžné poskytování seznamu hodnot IN pro kontrolu členství.

Zde je rychlé použití.

Předpokládejme, že máme tabulky zákazníků a plateb ve falešné půjčovně DVD a chceme odměnit našich pět nejlepších zákazníků s nejvyšší útratou, kteří si půjčili filmy ve dnech 10. až 13. dubna.

Představte si, že je to zvláštní cílové období. Pokud tedy zákazník utratil více než 30 USD, chceme ho uznat.

Mějte na paměti, že existují další dostupné možnosti řešení tohoto typu otázek (tj. spojení, zachycování výsledků z více výběrů atd...), ale poddotazy to zvládnou také.

Začneme tady celým šampionem. Tento úplný dotaz vrátí vše, co pro tuto konkrétní otázku chceme.

dvdrental=> SELECT first_name, last_name, email
FROM customer
WHERE customer_id IN (
SELECT customer_id FROM (
SELECT DISTINCT customer_id, SUM(amount)
FROM payment
WHERE extract(month from payment_date) = 4
AND extract(day from payment_date) BETWEEN 10 AND 13
GROUP BY customer_id
HAVING SUM(amount) > 30
ORDER BY SUM(amount) DESC
LIMIT 5) AS top_five);

Tento příklad ve skutečnosti obsahuje vnořené poddotazy, z nichž jeden je odvozená tabulka.

Začněme vrtáním do nejvnitřnějšího poddotazu, do odvozené tabulky.

Tento dílčí dotaz je samostatným příkazem SELECT, který vrací customer_id a SUM() ve sloupci částka.

Řez provádějí pouze zákazníci splňující kritéria kontrolovaná klauzulemi WHERE a HAVING, kteří jsou dále ztenčeni pomocí LIMIT 5;

Proč se ptáte na další dílčí dotaz?

Nemůžeme zde jednoduše použít WHERE customer_id IN části nejvzdálenějšího SELECT?

Podívejme se na to s praktickým přístupem.

Odeberu AS top_five z poddotazu a zkusím s ním nyní nejvzdálenější dotaz:

dvdrental=> SELECT first_name, last_name, email
FROM customer
WHERE customer_id IN
(SELECT DISTINCT customer_id, SUM(amount)
FROM payment
WHERE extract(month from payment_date) = 4
AND extract(day from payment_date) BETWEEN 10 AND 13
GROUP BY customer_id
HAVING SUM(amount) > 30
ORDER BY SUM(amount) DESC
LIMIT 5);
ERROR: subquery has too many columns
LINE 3: WHERE customer_id IN (

Zde se členství IN testuje pouze se sloupcem customer_id, ale odvozená tabulka vrací dva sloupce a PostgreSQL nás o tom informuje.

Jedním z řešení je použití jiného dílčího dotazu. Výběrem pouze customer_id ze sady výsledků odvozené tabulky vytvoříte další vnitřní vnořený poddotaz.

Nyní predikát IN obsahuje více řádků hodnot jednoho sloupce, aby bylo možné zkontrolovat členství v klauzuli WHERE pro customer_id, aby byly nastaveny konečné výsledky.

Proč na tom záleží?

Využití poddotazů tímto způsobem je účinné vzhledem k počtu hodnot, které by mohly být potenciálně testovány s predikátem IN().

Představte si, že by jich bylo 100? Nebo více?

'Pevné kódování ' všechny v seznamu IN() by se mohly stát problematickými a náchylnými k chybám, protože objem hodnot roste.

4. create_series()

Tato funkce vrácení sady je šikovná a její používání a prozkoumávání je super. Použil jsem create_series() ve výše uvedených příkladech, ale zaslouží si vlastní rozhovor. Více se zaměřte na funkce a možnosti.

Generovat_series() považuji za užitečné pro srovnávací dotazy, kde některá nebo všechna data chybí.

Nebo jsou v době, kdy zkoumám, k dispozici pouze částečná data. Jedním z užitečných způsobů použití je naplnění tabulek 'fiktivními daty '.

Pro začátek si vytvoříme jednoduchou tabulku:

trial=> CREATE TABLE tbl_1(
trial(> tb_id SERIAL PRIMARY KEY,
trial(> some_day DATE,
trial(> an_amt NUMERIC(4,2));
CREATE TABLE

Potom použijte create_series() jako VALUES pro náš příkaz INSERT:

trial=> INSERT INTO tbl_1(some_day, an_amt)
VALUES(
generate_series('2018-04-01','2018-04-15',INTERVAL '1 day'),
generate_series(2.43, 34.20, 1.03));
INSERT 0 31

Poté vytvořte druhou tabulku

trial=> CREATE TABLE tbl_2(
tb2_id SERIAL PRIMARY KEY,
some_day2 DATE,
an_amt2 NUMERIC(4,2));
CREATE TABLE

Také jej naplňte pomocí create_series() v příkazu INSERT:

trial=> INSERT INTO tbl_2(some_day2, an_amt2)
VALUES(
generate_series('2018-05-16','2018-05-31',INTERVAL '1 day'),
generate_series(15.43, 31., 1.03));
INSERT 0 16

Proč na tom záleží?

Pro zopakování, generation_series() je velmi užitečné pro vytváření simulovaných nebo cvičných dat.

Zjistil jsem, že napodobování měsíčních nebo denních rozsahů pro srovnání je výjimečné s generovat_series(). Toto použití ukazuje část 1 a CTE.

Velkou hodnotu má také vytvoření sady úplných dat pomocí generation_series() a jejich použití k porovnání s uloženými daty, aby se zjistilo, zda některá data chybí.

5. Dotaz s agregační funkcí COUNT().

Tato jednoduchá, ale účinná agregační funkce by měla být v arzenálu každého. Zejména při prvním zkoumání tabulek nebo datových souborů.

Chci říct, opravdu chcete 'VYBRAT vše ' z tabulky s 1 milionem řádků?

Před načtením určete pomocí COUNT(*), kolik záznamů je přítomno.

Pojďme zjistit, kolik řádků má filmová tabulka v této simulované tabulce půjčovny DVD:

dvdrental=> SELECT COUNT(*)
dvdrental-> FROM film;
count
-------
1000
(1 row)

I když to není tak rozsáhlé jako 1M+ řádků, jsem si jistý, že vidíte užitečnost.

Chcete-li vrátit počet konkrétních řádků, lze COUNT(*) filtrovat pomocí klauzule WHERE.

Podívejme se, kolik filmů má hodnocení 'G':

dvdrental=> SELECT COUNT(*)
dvdrental-> FROM film
dvdrental-> WHERE rating = 'G';
count
-------
178
(1 row)

Je třeba si uvědomit další formu COUNT(). POČET(nějaký_výraz) .

Rozdíly mezi nimi jsou:

  • COUNT(*) vrátí součet všech vstupních řádků (včetně NULLS a duplikátů).
  • POČET(nějaký_výraz ) počítá počet vstupních řádků, které nemají hodnotu NULL.

Při použití ve spojení s klíčovým slovem DISTINCT funkce COUNT() odstraní duplicitní položky a vrátí pouze jedinečné hodnoty.

Podívejme se, že v akci pomocí COUNT() s DISTINCT určíme, kolik jedinečných typů hodnocení existuje:

dvdrental=> SELECT COUNT(DISTINCT rating) FROM film;
count
-------
5
(1 row)

Díky tomuto dotazu víme, že existuje 5 typů hodnocení.

Proč na tom záleží?

V závislosti na tom, co je sledováno nebo zacíleno, může být důležité vědět, kolik něčeho existuje. Proto použití COUNT(*) nebo COUNT(nějaký_výraz ) pomáhá s těmito typy výzev.

Pamatujte, že COUNT(*) neignoruje hodnotu NULL. Všechny řádky, včetně duplicitních hodnot a hodnot NULL, jsou vráceny jako součást konečného čísla.

6. UPDATE více řádků výrazem CASE.

Předpokládejme, že máme tuto tabulku:

trial=> SELECT * FROM reward_members;
rm_id | expense_amt | member_status
-------+-------------+---------------
1 | 1245.33 | gold
2 | 1300.49 | gold
3 | 900.20 | bronze
4 | 2534.44 | platinum
5 | 600.19 | bronze
6 | 1001.55 | silver
7 | 1097.99 | silver
8 | 3033.33 | platinum
(8 rows)

Musíme přejmenovat sloupec member_status a přidat 'group ' na konec aktuálního názvu každého záznamu.

Pro začátek to bez problémů provede několik jednotlivých příkazů UPDATE.

Ale stejně tak může být i výraz s jedním CASE.

trial=> UPDATE reward_members
SET member_status = (
CASE member_status
WHEN 'gold' THEN 'gold_group'
WHEN 'bronze' THEN 'bronze_group'
WHEN 'platinum' THEN 'platinum_group'
WHEN 'silver' THEN 'silver_group'
END
)
WHERE member_status IN ('gold', 'bronze','platinum', 'silver');
UPDATE 8

Pojďme se znovu dotázat na tabulku, abychom viděli změny:

trial=> SELECT * FROM reward_members;
rm_id | expense_amt | member_status
-------+-------------+----------------
1 | 1245.33 | gold_group
2 | 1300.49 | gold_group
3 | 900.20 | bronze_group
4 | 2534.44 | platinum_group
5 | 600.19 | bronze_group
6 | 1001.55 | silver_group
7 | 1097.99 | silver_group
8 | 3033.33 | platinum_group
(8 rows)

Všechny aktualizace byly úspěšné.

Proč na tom záleží?

Dokážete si představit, kolik zpátečních cest by to trvalo na server, kdyby bylo spuštěno více jednotlivých příkazů UPDATE. Ve skutečnosti jen 4 pro tento příklad. Potenciál pro mnohé však stále existuje.

Přesto pomocí výrazu UPDATE s CASE posíláme místo toho pouze jeden dotaz.

7. COPY a \copy

PostgreSQL poskytuje COPY, příkaz pro export dat mezi soubory a tabulkami.

Ujistěte se, že navštívíte poskytnutý odkaz, kde uvidíte velké množství možností dostupných s COPY.

Důležitá poznámka týkající se COPY. K provedení tohoto příkazu je vyžadováno oprávnění role SUPERUSER.

Metapříkaz psql \copy je alternativou pro uživatele, kteří tento atribut role nepovažují. Brzy tento příkaz navštívíme.

Nejprve spusťte příkaz COPY pro export určitých sloupců do souboru CSV na místním počítači.

Předpokládejme, že máme tento výsledek dotazu pro export:

trial=# SELECT expense_amt, member_status
trial-# FROM reward_members
trial-# WHERE member_status = 'gold_group';
expense_amt | member_status
-------------+---------------
1245.33 | gold_group
1300.49 | gold_group
(2 rows)

S COPY můžeme použít příkaz SELECT k dokončení tohoto exportu.

trial=# COPY (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'gold_group')
TO '/home/linux_user_here/awards_to_honor.csv'
DELIMITER ','
CSV HEADER;
COPY 2

*Poznámka:Podle dokumentace musí být dotaz v závorkách.

Pojďme nyní zkontrolovat obsah tohoto souboru:

$ cat awards_to_honor.csv
expense_amt,member_status
1245.33,gold_group
1300.49,gold_group

Vidíme, že první řádek obsahuje HEADER (což jsou názvy sloupců) a oba řádky obsahují data cost_amt a member_status pro oba sloupce vrácené filtrem klauzule WHERE.

Další důležité upozornění, které jsem objevil při provádění výše uvedeného příkazu COPY.

Uživatel musí mít oprávnění k zápisu do souboru na úrovni OS.

V mém případě opraveno pomocí:

$ sudo chown postgres awards_to_honor.csv

Tomuto problému se můžete vyhnout zápisem do systémového souboru, ke kterému má aktuální uživatel přístup, jako je /tmp (zobrazeno níže.)

trial=# COPY (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'gold_group')
TO '/tmp/awards_to_honor.csv'
DELIMITER ','
CSV HEADER;
COPY 2

Jedna z mých testovacích rolí bez atributu SUPERUSER však narazila na problémy se zápisem do souboru /tmp.

Potvrzení viz níže:

trial=# SET role log_user; -- changing from postgres user to log_user
SET

Nyní se pokoušíte o stejný příkaz COPY, zápis do složky /tmp

trial=> COPY (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'gold_group')
TO '/tmp/awards_to_honor2.csv'
DELIMITER ','
CSV HEADER;
ERROR: must be superuser to COPY to or from a file
HINT: Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.

Možná lepším měřítkem, jak je navrženo v HINT:, pro role bez atributu SUPERUSER, je metapříkaz psql \copy.

Pojďme provést podobný typ příkazu s \copy místo toho s použitím stejné role, aniž bychom potřebovali atribut SUPERUSER.

trial=> \copy (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'silver_group')
TO '/home/linux_user_here/more_awards.csv'
DELIMITER ','
CSV HEADER;
COPY 2

Žádné problémy.

A obsah souborů

$ cat more_awards.csv
expense_amt,member_status
1001.55,silver_group
1097.99,silver_group

Funguje také pro složku /tmp:

trial=> \copy (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'silver_group')
TO '/tmp/more_awards.csv'
DELIMITER ','
CSV HEADER;
COPY 2

Stejný obsah obsažený také v zapsaném souboru:

trial=> \! cat /tmp/more_awards.csv
expense_amt,member_status
1001.55,silver_group
1097.99,silver_group

Proč na tom záleží?

Import dat do PostgreSQL prostřednictvím souborů je spolehlivá metoda hromadného nahrávání. Ačkoli tento příspěvek na blogu nepokrývá všechny, COPY a \copy oba nabízejí několik možností pro práci s různými formáty souborů a příponami.

Na stejném tokenu lze export dat z tabulek nebo konkrétních sloupců snadno zvládnout také pomocí obou těchto příkazů.

8. psql \help meta-příkaz

Nacházíte se v relaci příkazového řádku psql. Zajímá vás syntaxe příkazu CREATE INDEX?

Není potřeba a jít do prohlížeče nebo jiného dokumentu.

Zkuste toto:

trial=> \help CREATE INDEX
Command: CREATE INDEX
Description: define a new index
Syntax:
CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON table_name [ USING method ]
( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
[ WITH ( storage_parameter = value [, ... ] ) ]
[ TABLESPACE tablespace_name ]
[ WHERE predicate ]

Chcete-li vědět, jaký text nápovědy je k dispozici, můžete spustit \help samostatně a získat seznam dostupných možností.

Nebudu je zde všechny vypisovat, jen vím, že tato možnost je k dispozici.

Proč na tom záleží?

Skutečnost, že tento meta-příkaz je super snadno použitelný, výkonný a pohodlný, je dostatečným množstvím kladů, abychom to zde zmínili. Ušetřilo mi to spoustu času stráveného hledáním v jiné dokumentaci. A jako nováček to samozřejmě používám docela často!

Závěr

Toto není vyčerpávající seznam. Ani 'buďte všichni, konec všech ' dotazů a manipulace s daty.

Pouze můj názor na ty, které mě zajímají a mluví se mnou, když se dále učím a rostu v roli vývojáře SQL. Doufám, že prostřednictvím tohoto příspěvku na blogu najdete případy použití pro výše uvedené dotazy a příkazy a implementujete ty, které uznáte za vhodné.


  1. Přehled programování na straně serveru v PostgreSQL

  2. PostgreSQL je nejlepší databáze na světě

  3. Základy ladění MySQL na dedikovaných serverech

  4. Jak nastavit počáteční hodnotu a automatický přírůstek v MySQL?