PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Моите любими PostgreSQL заявки и защо са важни

Базите данни, таблиците, нормализирането и стабилният план за архивиране ни позволяват да съхраняваме и поддържаме данни.

Тези комбинирани най-добри практики от своя страна ни позволяват взаимодействие с тези данни. В днешния свят, управляван от данни, данните са ценни. Не само ценни, данните често са от решаващо значение за решенията на крайния потребител, предоставяни от продукти и услуги. Извличането на прозрения, отговаряне на въпроси и смислени показатели от данни чрез заявки и манипулиране на данни е неразделен компонент на SQL като цяло.

PostgreSQL не е по-различен.

Тази основна същност е от решаващо значение за успеха във всеки аспект, управляван от данни.

По-долу представям комбинация от 8 различни заявки или видове заявки, които намирам за интересни и ангажиращи да изследвам, изучавам, научавам или по друг начин манипулирам набори от данни.

Те не са изброени в никакъв ред по важност.

Повечето вероятно ще бъдат познати стари приятели. Може би някои ще станат нови познати.

Използваните примерни таблици и данни не са толкова важни, колкото действителната конструкция на самите заявки и това, което всяка заявка връща, предлага или предоставя. Много от тях са фалшиви и са извлечени за демонстрационни цели и не трябва да се приемат буквално в техните стойности.

1. Ляво присъединяване, имайте предвид всички нули вдясно...

Да предположим, че в този пример имаме текуща разпродажба от два месеца и получаваме общо и двете заедно.

И все пак по някаква причина вторият месец не изтегли тежестта си и искаме да се насочим към кои дни месец първият е набрал хлабината.

Тези продажби са представени като плащане на таблици и fake_month за тази демонстрация.

За отбелязване:

  • Ще проверяваме само за суми, по-големи от 2000.
  • Ще ограничим изхода само до 10 реда.

За начало имаме този „генериращ израз на обща таблица (CTE). ' таблицата fake_month за нас и следната заявка.

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)

Изглежда, че и двата месеца са допринесли за това. И така, това решено ли е?

Преди да считаме, че това е решено, нека да посетим клаузата ORDER BY.

Разбира се, можете да ПОРЪЧАТЕ ПО ASC или DESC.

Въпреки това, можете също да ПОРЪЧАТЕ ОТ NULL първо или последно и това променя нещата малко.

Нека да пренапишем тази заявка и първо да използваме ORDER BY NULLS в легитимната колона.

За краткост ще премахна CTE от изхода, просто знайте, че все още е там и се използва.

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)

Няма никаква разлика.

Ами ако ПОРЪЧАМЕ С NULL първо в колоната фалшиви? Този от дясно страна на JOIN?

Да видим.

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)

Сега стигаме до някъде. Можем да видим за дни 29 и 30, фалшивата колона е поръчана от горната част на набора от резултати.

Поради първо ORDER BY фалшиви NULL.

Това решава нашия въпрос, до кои дни е отложено „разпродажбата 2“.

Чудите ли се...

Можем ли просто да филтрираме с WHERE fake IS NULL? "

Като това:

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)

Да, това работи. Така че защо просто не използвате тази заявка вместо това? Защо има значение?

Смятам, че използването на LEFT JOIN и ORDER BY NULLS първо за таблицата от дясната страна на JOIN е чудесен начин да изследвате непознати таблици и набори от данни.

Като потвърдите какви данни, ако има такива, „липсват ’ първо от тази страна на условието за свързване; подобрява яснотата и информираността, което ви позволява да филтрирате набора от резултати с клаузата WHERE IS NULL, като финализирате нещата.

Разбира се, запознаването с таблиците и наборите от данни може потенциално да премахне необходимостта от представеното тук LEFT JOIN.

Това е достойна заявка за всеки, който използва PostgreSQL, поне да опита по време на проучване.

2. Конкатенация на низове

Конкатенацията, свързването или добавянето на два низа, предоставя опция за представяне на набори от резултати. Много „неща ' може да бъде свързан.

Въпреки това, както е отбелязано в документацията, операторът за конкатенация на низове ('||') приема не-низов вход, стига единият да е низ.

Нека видим някои примери със следните заявки:

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

Виждаме, че числата и низовете могат да бъдат свързани заедно, както беше споменато по-горе.

"||" операторът е само един от наличните в PostgreSQL.

Функцията concat() приема множество аргументи, като ги конкатенира всички при връщане.

Ето пример за тази функция в действие:

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

Можем да предадем повече от два аргумента, ако желаем:

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

Нека да отбележим нещо много бързо със следните примери:

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)

Обърнете внимание, че функцията concat() игнорира NULL, независимо къде е поставена в списъка с параметри, докато операторът за конкатенация на низове не го прави.

NULL се връща, ако присъства някъде в низа за конкатенация.

Просто имайте предвид това.

Вместо да включва ръчно в низа, който трябва да се конкатенира, PostgreSQL включва също функция concat_ws(), която приема разделител на низове като първи параметър.

Ще го посетим със следните запитвания:

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() приема числа или низове като аргументи и както е посочено по-горе, използва първия аргумент като разделител.

Как concat_ws() третира 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 се игнорира, освен ако не е аргументът разделител, даден на concat_ws().

След това всички аргументи се игнорират и вместо това се връща NULL.

Конкатенацията е готина...

Сега, когато имаме представа как работи конкатенацията, нека разгледаме няколко примера за това.

Обратно към фалшивата база данни за DVD под наем

Да предположим, че трябва да съставим списък с имена и фамилия на клиенти, заедно с техния имейл адрес, за да изпратим бележка за актуализиране на акаунта им.

Ще огранича изхода само до 10 реда за краткост, но все пак ще демонстрирам || оператор.

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)

Забележете, че трябваше да избегнем единичната кавичка, използвана с апостроф s, като използваме допълнителна единична кавичка, за да покажем притежанието на имейл адреса за всеки клиент.

Защо трябва да знаете?

Може да има моменти, когато конкатенирането на данни ви предоставя по-добро разбиране и разбиране на набора от данни, с който работите. Наред с опциите за отчитане, обединяването на споделени набори от данни с други може потенциално да ги направи (данните) по-четливи и смилаеми.

3. Доставящ списък със стойности на IN с подзаявки

Подзаявката има много мощни приложения. От тях предоставянето на IN списък със стойности за проверка за членство е често срещано.

Ето една бърза употреба.

Да предположим, че имаме таблици за клиенти и плащания в фалшив магазин за отдаване под наем на DVD и искаме да наградим петте си клиенти с най-високи разходи, които са наели филми през дните от 10 до 13 април.

Представете си, че това е специален целеви период. Така че, ако клиентът е похарчил повече от $30, искаме да го потвърдим.

Имайте предвид, че има и други налични опции за решаване на този тип въпроси (т.е. обединяване, улавяне на резултати от множество избори и т.н.), но подзаявките също могат да се справят с него.

Ще започнем с целия шебанг тук. Тази пълна заявка връща всичко, което искаме за този конкретен въпрос.

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

Този пример всъщност съдържа вложени подзаявки, една от които е извлечена таблица.

Нека започнем с разбивка на най-вътрешната подзаявка, тази извлечена таблица.

Тази подзаявка е самостоятелен оператор SELECT, който връща customer_id и SUM() в колоната за сумата.

Само тези клиенти, отговарящи на критериите, проверени от клаузите WHERE и HAVING, правят изрязването, като допълнително се изтъняват с LIMIT 5;

Защо питате следващата подзаявка?

Не можем ли просто да използваме WHERE customer_id IN частта от най-външния SELECT тук?

Нека да видим с практически подход.

Ще премахна AS top_five от подзаявката и ще опитам най-външната заявка с нея сега:

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 (

Тук членството в IN се тества само с колоната customer_id, но извлечената таблица връща две колони и PostgreSQL ни уведомява.

Едно средство е да използвате друга подзаявка. Избирането само на customer_id от набора резултати на извлечената таблица създава следващата вътрешна вложена подзаявка.

Сега предикатът IN съдържа множество реда със стойности на една колона, за да провери членството спрямо клаузата WHERE за customer_id, за да направи крайния набор от резултати.

Защо има значение?

Използването на подзаявки по този начин е мощно поради факта на броя на стойностите, които потенциално биха могли да бъдат тествани с предиката IN().

Представете си, ако имаше 100? Или повече?

'Твърдо кодиране ' всички те в списъка IN() могат да станат проблематични и податливи на грешки с увеличаване на обема на стойностите.

4. генериране_серия()

Тази функция за връщане на набор е удобна и супер забавна за използване и изследване. Използвал съм generate_series() в горните примери, но заслужава отделен разговор. Фокусиране повече върху функцията и възможностите.

Намирам generate_series() за полезен за сравнителни заявки, при които някои или всички данни липсват.

Или само частични данни са налични в момента, в който проучвам. Една удобна употреба е попълването на таблици с „фиктивни данни '.

За да започнем, ще създадем проста таблица:

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

След това използвайте generate_series() като VALUES за нашия израз 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

След това създайте втора таблица

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

Също така го попълнете с помощта на generate_series() в оператора 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

Защо има значение?

За да повторя, generate_series() е толкова полезен за създаване на фалшиви или практически данни.

Открих, че имитирането на диапазони от месеци или дни за сравнение е изключително с generate_series(). Вижте раздел 1 и CTE там, демонстрира тази употреба.

Създаването на набор от пълни данни с generate_series() и използването за сравнение със съхранени данни, за да се определи дали липсват данни, също има голяма стойност.

5. Заявката е с агрегатната функция COUNT() .

Тази проста, но ефективна агрегатна функция трябва да бъде в арсенала на всеки. Особено когато изследвате таблици или набори от данни за първи път.

Искам да кажа, наистина ли искате да „ИЗБЕРЕТЕ всичко ' от таблица с 1 милиона реда?

Определете с COUNT(*) колко записа има, преди да заредите.

Нека разберем колко реда има таблицата за филми в тази фалшива таблица за наем на DVD:

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

Въпреки че не е толкова обширна, колкото 1M+ реда, сигурен съм, че виждате полезността.

За да върнете броя на конкретните редове, COUNT(*) може да се филтрира с клауза WHERE.

Нека видим колко филма имат рейтинг „G“:

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

Има и друга форма на COUNT(), за която трябва да знаете. COUNT(някакъв_израз) .

Разликите между тях са:

  • COUNT(*) връща общата сума на всички въведени редове (включително NULLS и дубликатите).
  • COUNT(някакъв_израз ) отчита броя на входните редове, различни от NULL.

Когато се използва заедно с ключовата дума DISTINCT, COUNT() ще премахне дублиращите се записи и ще върне само уникални стойности.

Нека да видим, че в действие използваме COUNT() с DISTINCT, за да определим колко уникални типа оценки присъстват:

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

С тази заявка знаем, че има 5 типа оценки.

Защо има значение?

В зависимост от това какво се проследява или насочва, знанието колко от нещо съществува може да бъде важно. Следователно, използвайки COUNT(*) или COUNT(някой_израз ) помага при тези видове предизвикателства.

Само не забравяйте, че COUNT(*) не игнорира NULL. Всички редове, включително дублирани и NULL стойности, се връщат като част от крайното число.

6. АКТУАЛИЗИРАНЕ на няколко реда с израз CASE.

Да предположим, че имаме тази таблица:

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)

Трябва да преименуваме колоната member_status и да добавим 'group ' до края на текущото име, присъстващо за всеки запис.

Като за начало, множество отделни оператори UPDATE ще постигнат това без проблем.

Но също така може и един израз 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

Нека да потърсим отново таблицата, за да видим промените:

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)

Всички актуализации бяха успешни.

Защо има значение?

Можете да си представите колко двупосочни пътувания би отнело това до сървъра, ако бяха изпълнени множество отделни оператори UPDATE. Всъщност само 4 за този пример. Но все пак потенциалът за много хора винаги е налице.

И все пак, използвайки UPDATE с израз CASE, вместо това изпращаме само една заявка.

7. COPY и \copy

PostgreSQL предоставя COPY, команда за експортиране на данни между файлове и таблици.

Уверете се и посетете предоставената връзка, за да видите изобилния брой опции, налични с COPY.

Важна забележка относно COPY. За изпълнението на тази команда е необходимо привилегия на ролята на SUPERUSER.

Метакомандата psql \copy е алтернатива за тези потребители, които не считат този атрибут за роля. Скоро ще посетим тази команда на свой ред.

Първо, нека изпълним команда COPY, за да експортираме определени колони в CSV файл на локалната машина.

Да приемем, че имаме този резултат от заявката за експортиране:

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)

С COPY можем да използваме този оператор SELECT, за да завършим този експорт.

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

*Забележка:Съгласно документацията, заявката трябва да е в скоби.

Нека сега проверим съдържанието на този файл:

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

Можем да видим, че първият ред съдържа HEADER (които са имената на колоните) и двата реда имат данните за cost_amt и member_status за двете колони, върнати от филтъра на клаузата WHERE.

Друго важно предупреждение, което открих при изпълнението на горната команда COPY.

Потребителят трябва да има права да пише във файла на ниво ОС.

В моя случай, коригирано с:

$ sudo chown postgres awards_to_honor.csv

Можете да избегнете този проблем, като вместо това пишете в системен файл, до който текущият потребител има достъп, като /tmp (показан по-долу.)

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

Една от моите тестови роли без атрибута SUPERUSER обаче се сблъска с проблеми при записване във файла /tmp.

Вижте по-долу за потвърждение:

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

Сега се опитваме да използваме същата команда COPY, като пишем в папката /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.

Може би по-добра мярка, както се предлага в HINT:, за роли без атрибута SUPERUSER е метакомандата psql \copy.

Нека изпълним подобен тип команда с \copy, вместо да използваме същата роля, без да е необходим този атрибут 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

Няма проблеми.

И съдържанието на файловете,

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

Работи и за папката /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

Същото съдържание присъства и в писмения файл:

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

Защо има значение?

Импортирането на данни в PostgreSQL чрез файлове е сигурен метод за групово качване. Въпреки че всички не са обхванати в тази публикация в блога, COPY и \copy и двете предлагат няколко опции за работа с различни файлови формати и разширения.

На същия токен експортирането на данни от таблици или конкретни колони се обработва лесно и с двете команди.

8. psql \help мета-команда

Вие сте в psql сесия от команден ред. Интересувате ли се от синтаксиса на командата CREATE INDEX?

Няма нужда и да отидете в браузър или друг документ.

Опитайте това вместо това:

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 ]

За да разберете какъв помощен текст е наличен, можете да стартирате \help самостоятелно и да получите списък с налични опции.

Няма да ги изброявам всички тук, просто знайте, че тази опция е налична.

Защо има значение?

Фактът, че тази мета-команда е супер лесна за използване, мощна и удобна, е достатъчно плюс, за да я споменем тук. Това ми спести много време, прекарано в търсене в друга документация. И разбира се, тъй като съм новак, го използвам доста често!

Заключение

Това не е изчерпателен списък. Нито „бъдете всички край на всички ' на заявки и манипулиране на данни.

Само моето отношение към онези, които предизвикват интереса ми и ми говорят, докато продължавам да уча и да се развивам в ролята на SQL разработчик. Надявам се чрез тази публикация в блога да намерите случаи на употреба за горните заявки и команди, като приложите тези, където сметнете за добре.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да приложим приоритети в SQL (postgres)

  2. отпечатване на стойност на променлива в postgresql

  3. Еквивалентни на MySQL HEX() и UNHEX() в Postgres?

  4. Разбиране на ограниченията за проверка в PostgreSQL

  5. Как да изберете записи от последните 24 часа в PostgreSQL