PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Le mie query PostgreSQL preferite e perché sono importanti

Database, tabelle, normalizzazione e un solido piano di backup ci consentono di archiviare e mantenere i dati.

Queste migliori pratiche combinate, a loro volta, ci consentono di interagire con quei dati. Nel mondo odierno basato sui dati, i dati sono preziosi. Non solo preziosi, i dati sono spesso fondamentali per le soluzioni degli utenti finali fornite da prodotti e servizi. L'estrazione di informazioni dettagliate, la risposta a domande e metriche significative dai dati tramite query e manipolazione dei dati è una componente integrale di SQL in generale.

PostgreSQL non è diverso.

Questo nodo fondamentale è fondamentale per il successo in qualsiasi aspetto basato sui dati.

Di seguito, presento una combinazione di 8 diverse query o tipi di query che ho trovato interessanti e coinvolgenti da esplorare, studiare, apprendere o manipolare in altro modo i set di dati.

Non sono elencati in nessun ordine di importanza.

La maggior parte saranno probabilmente vecchi amici familiari. Forse alcuni diventeranno nuove conoscenze.

Le tabelle di esempio ei dati utilizzati non sono importanti quanto la costruzione effettiva delle query stesse e ciò che ciascuna query restituisce, offre o fornisce. Molti di loro sono derisi e derivati ​​a scopo dimostrativo e non dovrebbero essere presi alla lettera nei loro valori.

1. Unisciti a sinistra, fai attenzione a tutti i valori nulli a destra...

Supponiamo in questo esempio di avere una vendita in corso di due mesi e di ottenere un totale di entrambi combinati.

Tuttavia, per qualche ragione, il secondo mese non ha avuto il suo peso e vogliamo puntare ai giorni in cui il mese uno ha avuto un rallentamento.

Queste vendite sono rappresentate come tabelle di pagamento e fake_month per questa dimostrazione.

Da notare:

  • Verificheremo solo i totali superiori a 2000.
  • Limiteremo l'output a sole 10 righe.

Per iniziare, abbiamo questa Common Table Expression (CTE) 'generando ' la tabella fake_month per noi e la query che segue.

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)

Sembra che entrambi i mesi abbiano contribuito lì. Quindi è risolto?

Prima di considerare questo risolto, visitiamo la clausola ORDER BY.

Naturalmente, puoi ORDINARE PER ASC o DESC.

Tuttavia, puoi anche ORDINARE PER NULLS per primo o per ultimo e questo cambia un po' le cose.

Riscriviamo questa query e utilizziamo ORDER BY NULLS prima nella colonna legit.

Per brevità, rimuoverò il CTE dall'output, sappi solo che è ancora presente e in uso.

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)

Nessuna differenza lì.

Cosa succede se ORDIAMO PER NULLS prima sulla colonna falsa? Quello a destra lato della ISCRIVITI?

Vediamo.

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)

Adesso stiamo andando da qualche parte. Possiamo vedere per i giorni 29 e 30, la colonna falsa è stata ordinata dalla parte superiore del set di risultati.

A causa di ORDER BY falsi NULLS prima.

Questo risolve la nostra domanda, in quali giorni è stata rallentata la "vendita 2".

Ti stai chiedendo...

"Possiamo semplicemente filtrare con WHERE fake IS NULL? "

In questo modo:

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)

Sì, funziona. Allora perché non usare semplicemente quella query? Perché è importante?

Ritengo che l'utilizzo di LEFT JOIN e ORDER BY NULLS prima per la tabella sul lato destro di JOIN sia un ottimo modo per esplorare tabelle e set di dati sconosciuti.

Confermando quali dati sono "mancanti". ' prima su quel lato della condizione di unione; migliora la chiarezza e la consapevolezza, consentendoti di filtrare i risultati impostati con la clausola WHERE IS NULL, completando le cose.

Naturalmente, la familiarità con le tabelle e i set di dati potrebbe potenzialmente eliminare la necessità del LEFT JOIN presentato qui.

È una query degna per chiunque utilizzi PostgreSQL almeno per provare, durante l'esplorazione.

2. Concatenazione di stringhe

La concatenazione, l'unione o l'aggiunta di due stringhe, fornisce un'opzione di presentazione per i set di risultati. Molte 'cose ' può essere concatenato.

Tuttavia, come indicato nella documentazione, l'operatore di concatenazione di stringhe ('||') accetta input non stringa, purché uno sia una stringa.

Vediamo alcuni esempi con le seguenti query:

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

Possiamo vedere che numeri e stringhe possono essere tutti concatenati insieme come menzionato sopra.

Il '||' operatore è solo uno di quelli disponibili in PostgreSQL.

La funzione concat() accetta più argomenti, concatenandoli tutti al ritorno.

Ecco un esempio di quella funzione in azione:

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

Se lo desideri, possiamo passare più di due argomenti:

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

Notiamo qualcosa di molto veloce con questi prossimi esempi:

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)

Osserva che la funzione concat() ignora NULL indipendentemente da dove si trova nell'elenco dei parametri, mentre l'operatore di concatenazione di stringhe no.

Viene restituito NULL se presente in un punto qualsiasi della stringa da concatenare.

Basta essere consapevoli di questo.

Invece di includere manualmente all'interno della stringa da concatenare, PostgreSQL include anche una funzione concat_ws() che accetta un separatore di stringa come primo parametro.

Lo visiteremo con queste domande:

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() accetta numeri o stringhe come argomenti e, come indicato sopra, usa il primo argomento come separatore.

In che modo concat_ws() tratta 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)

NULL viene ignorato a meno che non sia l'argomento separatore fornito a concat_ws().

Quindi, tutti gli argomenti vengono ignorati e viene invece restituito NULL.

La concatenazione è fantastica...

Ora che abbiamo un'idea di come funziona la concatenazione, diamo un'occhiata a un paio di esempi.

Torna al database fittizio del noleggio di DVD

Supponiamo di dover compilare un elenco di nomi e cognomi dei clienti, insieme al loro indirizzo e-mail per inviare un promemoria per l'aggiornamento del loro account.

Limiterò l'output a sole 10 righe per motivi di brevità, ma continuando a dimostrare || operatore.

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)

Nota che abbiamo dovuto evitare la citazione singola usata con gli apostrofi, utilizzando una citazione singola aggiuntiva per mostrare il possesso dell'indirizzo email di ciascun cliente.

Perché dovresti saperlo?

Potrebbero esserci momenti in cui la concatenazione dei dati ti offre una migliore comprensione e comprensione del set di dati con cui stai lavorando. Insieme alle opzioni di reporting, la concatenazione di set di dati condivisi con quelli di altri potrebbe potenzialmente renderli (i dati) più leggibili e digeribili.

3. Fornitura di un elenco di valori IN con Subquery

Una sottoquery ha numerosi usi potenti. Di questi, fornire un elenco IN di valori per verificare l'appartenenza è comune.

Ecco un rapido utilizzo.

Supponiamo di avere tabelle clienti e pagamenti in un finto negozio di noleggio DVD e vogliamo premiare i nostri primi cinque clienti con la spesa più alta che hanno noleggiato film nei giorni dal 10 al 13 aprile.

Immagina che sia un periodo target speciale. Quindi, se il cliente ha speso più di $ 30, vogliamo riconoscerlo.

Tieni presente che ci sono altre opzioni disponibili per risolvere questo tipo di domanda (ad esempio, join, acquisizione di risultati da selezioni multiple, ecc...), ma anche le sottoquery possono gestirlo.

Inizieremo con l'intero shebang qui. Questa query completa restituisce tutto ciò che desideriamo per questa particolare domanda.

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

Questo esempio contiene effettivamente delle sottoquery nidificate, una delle quali è una tabella derivata.

Iniziamo analizzando la sottoquery più interna, quella tabella derivata.

Questa sottoquery è un'istruzione SELECT a sé stante, che restituisce un customer_id e un SUM() nella colonna dell'importo.

Solo i clienti che soddisfano i criteri verificati dalle clausole WHERE e HAVING effettuano il taglio, ulteriormente diradato con LIMIT 5;

Perché la prossima sottoquery che chiedi?

Non possiamo semplicemente usare la parte WHERE customer_id IN del SELECT più esterno qui?

Vediamo con un approccio pratico.

Rimuoverò AS top_five dalla sottoquery e proverò la query più esterna con esso ora:

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 (

Qui, l'appartenenza a IN viene testata solo con la colonna customer_id, ma la tabella derivata restituisce due colonne e PostgreSQL ce lo fa sapere.

Un rimedio consiste nell'utilizzare un'altra sottoquery. Selezionando solo il customer_id dal set di risultati della tabella derivata, viene creata la successiva subquery nidificata interna.

Ora il predicato IN contiene più righe dei valori di una colonna per verificare l'appartenenza rispetto alla clausola WHERE per customer_id per creare il set di risultati finali.

Perché è importante?

L'utilizzo di sottoquery in questo modo è potente a causa del numero di valori che potrebbero essere testati con il predicato IN().

Immagina se ci fosse un 100? O di più?

'Codifica rigida ' tutti nell'elenco IN() potrebbero diventare problematici e soggetti a errori all'aumentare del volume dei valori.

4. generate_series()

Questa funzione di ritorno del set è pratica e super divertente da usare ed esplorare. Ho usato generate_series() negli esempi precedenti, ma merita un discorso a parte. Concentrandosi maggiormente sulla funzione e sulle capacità.

Trovo generate_series() utile per query comparative in cui mancano alcuni o tutti i dati.

Oppure sono disponibili solo dati parziali nel momento in cui sto esplorando. Un pratico utilizzo è compilare le tabelle con 'dati fittizi '.

Per iniziare, creeremo una semplice tabella:

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

Quindi usa generate_series() come VALUES per la nostra istruzione 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

Quindi crea una seconda tabella

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

Inoltre, compilalo usando generate_series() nell'istruzione 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

Perché è importante?

Per ribadire, generate_series() è così utile per creare dati fittizi o di esercitazione.

Ho scoperto che imitare gli intervalli di mesi o giorni per il confronto è eccezionale con generate_series(). Fare riferimento alla sezione 1 e il CTE lì, dimostra questo uso.

Anche la creazione di un set di dati completo con generate_series() e l'utilizzo del confronto con i dati archiviati per determinare se mancano dei dati ha un grande valore.

5. Query con la funzione di aggregazione COUNT() .

Questa semplice ma efficace funzione di aggregazione dovrebbe essere nell'arsenale di chiunque. Soprattutto quando esplori tabelle o set di dati per la prima volta.

Voglio dire, vuoi davvero 'SELEZIONARE tutto ' da una tabella con 1 milione di righe?

Determina con COUNT(*) quanti record sono presenti prima di caricare.

Scopriamo quante righe ha il tavolo del film in questo finto tavolo per il noleggio di DVD:

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

Sebbene non sia così esteso come 1 milione di righe, sono sicuro che ne vedi l'utilità.

Per restituire il numero di righe specifiche, COUNT(*) può essere filtrato con una clausola WHERE.

Vediamo quanti film hanno una valutazione 'G':

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

C'è un'altra forma di COUNT() di cui essere a conoscenza. COUNT(qualche_espressione) .

Le differenze tra loro sono:

  • COUNT(*) restituisce il totale di tutte le righe di input (inclusi NULL e duplicati).
  • COUNT(qualche_espressione ) conta il numero di righe di input non NULL.

Se utilizzato insieme alla parola chiave DISTINCT, COUNT() eliminerà le voci duplicate e restituirà solo valori univoci.

Vediamolo in azione utilizzando COUNT() con DISTINCT per determinare quanti tipi univoci di valutazioni sono presenti:

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

Con questa query, sappiamo che esistono 5 tipi di valutazioni.

Perché è importante?

A seconda di ciò che viene monitorato o preso di mira, sapere quante cose esistono può essere importante. Pertanto, utilizzando COUNT(*) o COUNT(qualche_espressione ) aiuta con questo tipo di sfide.

Ricorda solo che COUNT(*) non ignora NULL. Tutte le righe, inclusi i valori duplicati e NULL, vengono restituite come parte del numero finale.

6. UPDATE più righe con un'espressione CASE.

Supponiamo di avere questa tabella:

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)

Dobbiamo rinominare la colonna member_status e aggiungere 'gruppo ' alla fine del nome corrente presente per ogni record.

Per cominciare, più istruzioni UPDATE individuali non risolveranno questo problema.

Ma anche una singola espressione 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

Interroghiamo nuovamente la tabella per vedere le modifiche:

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)

Tutti gli aggiornamenti sono riusciti.

Perché è importante?

Puoi immaginare quanti viaggi di andata e ritorno sarebbero necessari al server se fossero state eseguite più istruzioni UPDATE individuali. In verità, solo 4 per questo esempio. Tuttavia, il potenziale per molti è sempre lì.

Tuttavia, utilizzando un'espressione UPDATE con CASE, stiamo inviando invece solo una query.

7. COPIA e \copia

PostgreSQL fornisce COPY, un comando per esportare dati tra file e tabelle.

Assicurati di visitare il link fornito per vedere l'abbondante numero di opzioni disponibili con COPY.

Una nota importante sulla COPIA. Per eseguire questo comando è richiesto il privilegio del ruolo SUPERUSER.

Il meta-comando psql \copy è un'alternativa per quegli utenti che non hanno ritenuto questo attributo del ruolo. Visiteremo quel comando a turno a breve.

Innanzitutto, eseguiamo un comando COPY per esportare determinate colonne in un file CSV sul computer locale.

Supponiamo di avere questo risultato della query per l'esportazione:

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)

Con COPY, possiamo utilizzare l'istruzione SELECT per completare questa esportazione.

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

*Nota:secondo la documentazione, la query deve essere racchiusa tra parentesi.

Ora controlliamo il contenuto di quel file:

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

Possiamo vedere che la prima riga contiene HEADER (che sono i nomi delle colonne) ed entrambe le righe hanno i dati costs_amt e member_status per entrambe le colonne restituite dal filtro della clausola WHERE.

Un altro importante avvertimento che ho scoperto dall'esecuzione del comando COPY sopra.

L'utente deve disporre dei privilegi per scrivere sul file a livello di sistema operativo.

Nel mio caso, risolto con:

$ sudo chown postgres awards_to_honor.csv

Puoi evitare questo problema scrivendo invece in un file di sistema a cui l'utente corrente ha accesso come /tmp (mostrato di seguito).

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

Tuttavia, uno dei miei ruoli di test senza l'attributo SUPERUSER ha riscontrato problemi di scrittura nel file /tmp.

Vedi sotto per la conferma:

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

Ora sto provando lo stesso comando COPY, scrivendo nella cartella /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.

Forse una misura migliore, come suggerito nel SUGGERIMENTO:, per i ruoli senza l'attributo SUPERUSER, è il psql \copy meta-comando.

Eseguiamo un tipo di comando simile con \copy invece utilizzando lo stesso ruolo, senza la necessità di quell'attributo 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

Nessun problema lì.

E il contenuto dei file,

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

Funziona anche per la cartella /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

Stesso contenuto presente anche nel file scritto:

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

Perché è importante?

L'importazione di dati in PostgreSQL tramite file è un metodo di caricamento collettivo infallibile. Sebbene non siano tutti trattati in questo post del blog, COPY e \copy entrambi offrono diverse opzioni per lavorare con diversi formati di file ed estensioni.

Allo stesso modo, l'esportazione di dati da tabelle o colonne specifiche è facilmente gestibile anche con entrambi questi comandi.

8. psql \help meta-comando

Sei in una sessione della riga di comando di psql. Sei curioso della sintassi del comando CREATE INDEX?

Non c'è bisogno e vai su un browser o un altro documento.

Prova invece questo:

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 ]

Per sapere quale testo della guida è disponibile, puoi eseguire \help da solo e ottenere un elenco delle opzioni disponibili.

Non li elencherò tutti qui, sappi solo che l'opzione è disponibile.

Perché è importante?

Il fatto che questo meta-comando sia super facile da usare, potente e conveniente sono abbastanza vantaggi per menzionarlo qui. Mi ha fatto risparmiare un sacco di tempo speso a cercare in altra documentazione. E ovviamente, essendo un principiante, lo uso abbastanza spesso!

Conclusione

Questa non è una lista esaustiva. Né il 'be all end all ' di query e manipolazione dei dati.

Solo la mia opinione su quelli che suscitano il mio interesse e mi parlano mentre continuo a imparare e crescere in un ruolo di sviluppatore SQL. Spero che attraverso questo post del blog troverai casi d'uso per le query e i comandi di cui sopra, implementando quelli dove ritieni opportuno.