install postgresql
Установка
1
| sudo apt-get install postgresql postgresql-contrib
|
https://www.digitalocean.com/community/tutorials/how-to-install-postgresql-on-ubuntu-20-04-quickstart-ru Поле установки необходимо создать роли (пользователя postgres) Вход в консоль postgresql под юзером postgres
Для создания роли наберите в терминале следующую команду. И введите имя роли. Проще ввсети свое имя под которым вы работаете
1
| sudo -u postgres createuser --interactive
|
Далее создайте базу данных с таким же именем как и имя роли которую вы создали в пострес. Для этого наберите
Теперь находясь в терминале под своим именем вы можете просто войти в консоль postgres набрав команду
Основные команды для работы в консоли с postgresql
Просмотреть список баз данных
Далее в качестве примера приводится конспект по видео с youtube https://www.youtube.com/watch?v=WpojDncIWOw
Create DB and requests example
Cоздадим базу данных магазина
1
| postgres=# create database shop;
|
подключимся к базе данных
посмотрим какие есть таблицы в данной базе
Создание таблиц
Пока таблиц нет. Создадим таблицу сustomer
1
2
3
4
5
6
| shop=# create table customer(
shop(# id serial primary key,
shop(# name varchar(255),
shop(# phone varchar(30),
shop(# email varchar(255)
shop(# );
|
посмотрим созданную таблицу
Что покажет нам список таблиц
1
2
3
4
5
6
| List of relations
Schema | Name | Type | Owner
--------+-----------------+----------+-------
public | customer | table | anton
public | customer_id_seq | sequence | anton
(2 rows)
|
Посмотрим саму таблицу
1
2
3
4
5
6
7
8
9
| Table "public.customer"
Column | Type | Collation | Nullable | Default
--------+------------------------+-----------+----------+--------------------------------------
id | integer | | not null | nextval('customer_id_seq'::regclass)
name | character varying(255) | | |
phone | character varying(30) | | |
email | character varying(255) | | |
Indexes:
"customer_pkey" PRIMARY KEY, btree (id)
|
Coздадим таблицу продуктов
1
2
3
4
5
| shop=# create table product(
shop(# id serial primary key,
shop(# name varchar(255),
shop(# description text,
shop(# price integer);
|
1
2
3
4
5
6
7
8
9
| shop=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------------+----------+-------
public | customer | table | anton
public | customer_id_seq | sequence | anton
public | product | table | anton
public | product_id_seq | sequence | anton
(4 rows)
|
Создадим таблицу product_photo
1
2
3
4
| shop=# create table product_photo(
shop(# id serial primary key,
shop(# url varchar(255),
shop(# product_id integer references product(id));
|
В данной строке
1
| shop(# product_id integer references product(id));
|
устанавливает связь между таблицами product_photo и product
Создадим и другие таблицы
1
2
3
| shop=# create table cart(
shop(# customer_id integer references customer(id),
shop(# id serial primary key);
|
1
2
3
| shop=# create table cart_product(
shop(# cart_id integer references cart(id),
shop(# product_id integer references product(id));
|
Посмотрим все созданные таблицы
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| shop=# \d
List of relations
Schema | Name | Type | Owner
--------+----------------------+----------+-------
public | cart | table | anton
public | cart_id_seq | sequence | anton
public | cart_product | table | anton
public | customer | table | anton
public | customer_id_seq | sequence | anton
public | product | table | anton
public | product_id_seq | sequence | anton
public | product_photo | table | anton
public | product_photo_id_seq | sequence | anton
(9 rows)
|
Заполнение таблиц данными
Заполним наши таблицы
1
| shop=# insert into customer(name, phone, email) values('Василий', 02, 'vasya@mail.com');
|
1
2
| shop=# insert into customer(name, phone, email)
values('Петр', 03, 'petya@mail.com');
|
Выбрать все поля из таблицы customer
1
2
3
4
5
6
| shop=# select * from customer;
id | name | phone | email
----+---------+-------+----------------
1 | Василий | 2 | vasya@mail.com
2 | Петр | 3 | petya@mail.com
(2 rows)
|
Заполним таблицу product
1
2
3
4
5
| shop=# insert into product (name, description, price)
shop-# values ('iPhone', 'крутой телефон', 100000);
shop=# insert into product (name, description, price)
values ('Apple watch', 'крутые часы', 50000);
|
Посмотрим, что получилось
1
2
3
4
5
6
| shop=# select * from product;
id | name | description | price
----+-------------+----------------+--------
1 | iPhone | крутой телефон | 100000
2 | Apple watch | крутые часы | 50000
(2 rows)
|
Заполним таблицу product_photo
1
| shop=# insert into product_photo (url, product_id) values ('iphone_photo', 1);
|
Просмотрим существующие записи в таблице
1
2
3
4
5
| shop=# select * from product_photo;
id | url | product_id
----+--------------+------------
1 | iphone_photo | 1
(1 row)
|
Join
Потренируемся использовать join
1
| shop=# select * from product_photo pp;
|
1
2
3
4
5
| id | url | product_id
----+--------------+------------
1 | iphone_photo | 1
(1 row)
|
pp в данном случае alias (синоним полного названия таблицы) Попробуем join left
1
2
3
4
5
| shop=# select pp.* from product_photo pp left join product p on p.id = pp.product_id;
id | url | product_id
----+--------------+------------
1 | iphone_photo | 1
(1 row)
|
Если захотим посмотреть все поля
1
2
3
4
5
| shop=# select * from product_photo pp left join product p on p.id = pp.product_id;
id | url | product_id | id | name | description | price
----+--------------+------------+----+--------+----------------+--------
1 | iphone_photo | 1 | 1 | iPhone | крутой телефон | 100000
(1 row)
|
Eсли захотим посмотреть выборочные поля
1
2
3
4
5
| shop=# select pp.*, p.name from product_photo pp left join product p on p.id = pp.product_id;
id | url | product_id | name
----+--------------+------------+--------
1 | iphone_photo | 1 | iPhone
(1 row)
|
Попробуем добавить фото на несуществующий продукт. Для этого нам необходимо удалить внешний ключ из таблицы product_photo
1
| shop=# alter table product_photo drop constraint product_photo_product_id_fkey;
|
Наша таблица немного изменится было
1
2
3
4
5
6
7
8
9
10
11
| shop=# \d product_photo
Table "public.product_photo"
Column | Type | Collation | Nullable | Default
------------+------------------------+-----------+----------+-------------------------------------------
id | integer | | not null | nextval('product_photo_id_seq'::regclass)
url | character varying(255) | | |
product_id | integer | | |
Indexes:
"product_photo_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"product_photo_product_id_fkey" FOREIGN KEY (product_id) REFERENCES product(id)
|
Стало
1
2
3
4
5
6
7
8
9
| shop=# \d product_photo
Table "public.product_photo"
Column | Type | Collation | Nullable | Default
------------+------------------------+-----------+----------+-------------------------------------------
id | integer | | not null | nextval('product_photo_id_seq'::regclass)
url | character varying(255) | | |
product_id | integer | | |
Indexes:
"product_photo_pkey" PRIMARY KEY, btree (id)
|
Теперь мы можем создавать фотографию на несуществующий в базе данных продукт
1
| shop=# insert into product_photo (url, product_id) values ('unknown photo', 100);
|
Посмотрим, что получилось
1
2
3
4
5
6
| shop=# select * from product_photo;
id | url | product_id
----+---------------+------------
1 | iphone_photo | 1
2 | unknown photo | 100
(2 rows)
|
Посмотрим как теперь работает left join. Из левой таблицы выбираются все записи
1
2
3
4
5
6
| shop=# select pp.*, p.name from product_photo pp left join product p on p.id = pp.product_id;
id | url | product_id | name
----+---------------+------------+--------
1 | iphone_photo | 1 | iPhone
2 | unknown photo | 100 |
(2 rows)
|
И сравним это с тем как работает right join
1
2
3
4
5
6
| shop=# select pp.*, p.name from product_photo pp right join product p on p.id = pp.product_id;
id | url | product_id | name
----+--------------+------------+-------------
1 | iphone_photo | 1 | iPhone
| | | Apple watch
(2 rows)
|
Теперь из правой таблицы выбираются все записи ( в данном случае правая таблица - главная). По продукту Apple watch у нас не создано фото. Поэтому в полях id, url, product_id для продукта Apple watch значения - null
Теперь можно посмотреть как работает inner join. Просто заменим в запросе left join на inner join
1
2
3
4
5
| shop=# select pp.*, p.name from product_photo pp inner join product p on p.id = pp.product_id;
id | url | product_id | name
----+--------------+------------+--------
1 | iphone_photo | 1 | iPhone
(1 row)
|
Для запоминания приведем мнемоническую картинку для join ![[join.jpg]]
Удаление и обновление данных
Посмотрим еще раз нашу таблицу product_photo
1
2
3
4
5
6
| shop=# select * from product_photo;
id | url | product_id
----+---------------+------------
1 | iphone_photo | 1
2 | unknown photo | 100
(2 rows)
|
И удалим фото несуществующего товара
1
| shop=# delete from product_photo where id=2;
|
Обновим фото
1
| shop=# update product_photo set url='iphone_image2' where id=1;
|
1
2
3
4
5
| shop=# select * from product_photo;
id | url | product_id
----+---------------+------------
1 | iphone_image2 | 1
(1 row)
|
Select
Создадим заказ для одного из клиентов
1
| shop=# insert into cart (customer_id) values (1);
|
1
2
3
4
5
| shop=# select * from cart;
customer_id | id
-------------+----
1 | 1
(1 row)
|
Наполним только что созданную корзину продуктами посредством добавления продуктов в промежуточную таблицу cart_product. Добавим сразу два товара одним запросом
1
| shop=# insert into cart_product (cart_id, product_id) values (1, 1), (1, 2);
|
1
2
3
4
5
6
7
| shop=# select * from cart_product
;
cart_id | product_id
---------+------------
1 | 1
1 | 2
(2 rows)
|
Сложные запросы
Сформируем таблицу с именем клиента и с общей суммой заказов этого клиента
Достанем имена клиентов
1
| shop=# select c.name from customer c;
|
1
2
3
4
5
| name
---------
Василий
Петр
(2 rows)
|
Заджойним корзину
1
| shop=# select c.name, cart.id as cart_id from customer c left join cart on cart.customer_id=c.id;
|
1
2
3
4
5
| name | cart_id
---------+---------
Василий | 1
Петр |
(2 rows)
|
Используем еще один join
1
| shop=# select c.name, cart.id as cart_id from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id;
|
1
2
3
4
5
6
| name | cart_id
---------+---------
Василий | 1
Василий | 1
Петр |
(3 rows)
|
Выведем продукты Васи
1
| shop=# select c.name, cart.id as cart_id, cp.product_id from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id;
|
1
2
3
4
5
6
| name | cart_id | product_id
---------+---------+------------
Василий | 1 | 1
Василий | 1 | 2
Петр | |
(3 rows)
|
Еще добавим один join
1
| shop=# select c.name, cart.id as cart_id, p.name from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id left join product p on p.id=cp.product_id;
|
1
2
3
4
5
6
| name | cart_id | name
---------+---------+-------------
Василий | 1 | iPhone
Василий | 1 | Apple watch
Петр | |
(3 rows)
|
1
| shop=# select c.name, cart.id as cart_id, p.name, p.price from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id left join product p on p.id=cp.product_id;
|
1
2
3
4
5
6
| name | cart_id | name | price
---------+---------+-------------+--------
Василий | 1 | iPhone | 100000
Василий | 1 | Apple watch | 50000
Петр | | |
(3 rows)
|
Теперь пришла очередь проссумировать товары в корзине. Уберем лишние поля, сгруппируем и проссумируем, используем group by c.name
и sum(p.price)
1
| shop=# select c.name, sum(p.price) from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id left join product p on p.id=cp.product_id group by c.name;
|
1
2
3
4
5
| name | sum
---------+--------
Петр |
Василий | 150000
(2 rows)
|
У Петра есть поле null. Сделаем чтобы отображался 0
1
| shop=# select c.name, coalesce(sum(p.price), 0) as order_sum from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id left join product p on p.id=cp.product_id group by c.name;
|
1
2
3
4
5
| name | order_sum
---------+-----------
Петр | 0
Василий | 150000
(2 rows)
|
Выполним сортировку по сумме заказа
1
| shop=# select c.name, coalesce(sum(p.price), 0) as order_sum from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id left join product p on p.id=cp.product_id group by c.name order by order_sum desc;
|
1
2
3
4
5
| name | order_sum
---------+-----------
Василий | 150000
Петр | 0
(2 rows)
|
Если нам необходимо вывести только тех клиентов, которые что-то приборели, то есть у кого сумма заказа больше нуля, воспользуемся having
1
| shop=# select c.name, coalesce(sum(p.price), 0) as order_sum from customer c left join cart on cart.customer_id=c.id left join cart_product cp on cp.cart_id=cart.id left join product p on p.id=cp.product_id group by c.name having sum(p.price)>0;
|
1
2
3
4
| name | order_sum
---------+-----------
Василий | 150000
(1 row)
|
Отличие where от having
having фильтрует группы where фильтрует строки
Пример использования limit
1
| shop=# select * from customer order by name limit 1;
|
1
2
3
4
| id | name | phone | email
----+---------+-------+----------------
1 | Василий | 2 | vasya@mail.com
(1 row)
|
Выводится только один клиент Для смещения применяем offset
1
| shop=# select * from customer order by name limit 1 offset 1;
|
1
2
3
4
| id | name | phone | email
----+------+-------+----------------
2 | Петр | 3 | petya@mail.com
(1 row)
|
Что применяется часто для пагинации - разбивки больших массивов информации на страницы