123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- -- -----------------------------------------------------------------
- -- Задания
- -- -----------------------------------------------------------------
- -- 11.16 Выборка данных из других источников
- -- Выборка из подзапроса
- select genus_name from (
- select * from genus
- );
- -- Выборка анбора дат с интервалом в 2 месяца
- select date
- from generate_series('2020-01-01'::date,
- '2024-06-01'::date,
- '2 month'::interval) date;
- --
- select * from (values
- ('The Shawshank Redemption', 9.3, 1994),
- ('The Godfather', 9.2, 1972),
- ('The Dark Knight', 9.1, 2008),
- ('Inception', 8.8, 2010)
- ) t(movie, imdb_rating, year);
- -- -----------------------------------------------------------------
- -- 11.18 Фильтрация данных
- table family;
- select * from family where family_name='Дроздовые';
- select * from family where family_name='Дроздовые' or family_name='Синицевые';
- select * from family where family_name in ('Дроздовые', 'Синицевые');
- select * from family where family_name like '%а%';
- select * from family where family_name like '%а%' or family_name like '%с%';
- select * from family where family_name ilike '%а%';
- -- -----------------------------------------------------------------
- -- 11.19 Особое значение NULL, coalesce
- select family_id, family_name, coalesce(description, 'не заполнено') as description from family;
- select * from family where description is null;
- select * from family where description is null or family_name like '%Д%';
- -- -----------------------------------------------------------------
- -- 11.20 Сортировка данных
- select * from family order by family_id;
- select * from family order by description nulls first;
- select * from family order by sescription nulls last;
- select family_name from family where family_name like 'Д%' order by family_name;
- -- -----------------------------------------------------------------
- -- 11.21 Ограничение количества результатов запроса
- table species;
- select * from species order by species_name, description
- limit 10 offset 10;
- select species_id, species_name from species where primary_color ilike '%бел%'
- order by species_name
- limit 5;
- -- -----------------------------------------------------------------
- -- 11.22 Измененяем данные в БД
- select 'Птичка: ' || species_name птичка from species order by species_name;
- -- или через функцию format
- select format('Птичка: %s', species_name) as 'птичка'
- from species order by species_name;
- -- Обновить записа
- update species set species_name='Древесный дрозд'
- where species_name='Дрозд лесной';
- -- Удалить таблицу. Но команда упадет с ошибкой если таблицы нет или если
- -- на таблицу ссылается другая таблица.
- drop table something;
- -- Удалить таблицу. Но команда упадет если на таблицу ссылается другая таблица.
- drop table if exists something;
- -- Удалить таблицу.
- drop table if exists something cascade;
- -- Создание таблицы из данных другой таблицы
- create temp table crows as
- select * from species where genus_id=(
- select genus_id from genus where genus_name='Ворон');
- -- Создание таблицы из данных другой таблицы
- select * into crows from species s where s.genus_id=(
- select genus_id from genus g where g.genus_name='Ворон'
- );
- -- Обновление данных в таблице
- create table smth (a int);
- update smth set a = a * 2;
- -- -----------------------------------------------------------------
- -- 11.26 Работа со строками
- select species_name from species
- order by length(species_name) desc, species_name limit 5;
- -- -----------------------------------------------------------------
- -- 11.28 Работа со перечислениями
- create table color (
- name varchar(22) primary key check (name in (
- 'адовый красный',
- 'ядерный зеленый',
- 'подозрительная мурена'
- ))
- );
- create table color (
- name text check (length(name) between 4 and 20)
- );
- -- -----------------------------------------------------------------
- -- 11.29 Работа со временем
- select to_char(created_at, 'DD.MM.YYYY HH24:MI:SS') "дата инцидента",
- message "сообщение" from log;
- insert into log (created_at, message) values
- ('2024-07-31 20:19:51'::timestamp, 'Произошло страшное: сломался приём платежа #1128'),
- ('2024-07-31 17:19:52'::timestamp, 'Трындец с отправкой почты, похоже, почтовый сервер недоступен!'),
- ('2024-07-31 17:20:53'::timestamp, 'Ужас, всё работает!');
- drop table if exists log;
- create temp table log(
- log_id bigint generated always as identity,
- created_at timestamp not null,
- message text not null
- );
- insert into log (created_at, message) values
- ('2024-06-02 20:20:20'::timestamp, 'Это событие за прошлый год'),
- ('2025-06-02 20:20:20'::timestamp, 'Это событие за текущий год');
- table log;
- select * from log where extract(month from(created_at)) = extract(month from now())
- and extract(year from(created_at)) = extract(year from now());
- -- Вернуть данные за этот месяц
- select * from log
- where date_trunc('month', created_at) = date_trunc('month', current_timestamp)
- order by log_id;
- -- Вернуть данные за последнюю неделю
- select * from log where created_at >= current_date - interval '7 days'
- -- Удалить данные за последние 30 дней
- delete from log
- where created_at < current_date - intercal '30 days';
- -- Прибавить месяц
- select '2024-01-31'::date + '1 month'::interval;
- -- Прибавить год
- select '2024-02-29'::date + '1 year'::interval;
- -- Эти запросы вернут одинаковое значение
- select '2024-02-28'::date - '1 year'::interval;
- select '2024-02-29'::date - '1 year'::interval;
- -- Запрос вернет ответ типа integer
- select '2024-02-01'::date - '2023-01-01'::date d;
- -- Запрос вернет ответи типа interval
- select '2024-02-01'::timestamp - '2023-01-01'::timestamp d;
- -- Форматирование даты
- select
- to_char(start, 'DD.MM.YYYY') start,
- to_char(finish, 'DD.MM.YYYY') finish
- extract(day from (finish - start) delta_in_days
- from records order by start, finish;
- -- С помощью функции age можно вывести дельту
- select
- to_char(start, 'DD.MM.YYYY') start,
- to_char(finish, 'DD.MM.YYYY') finish
- age(finish, start) delta
- from records order by start, finish;
- -- Достает email тех у кого в апреле день рождения
- select email from employees
- where extract('month' from birthday)=4
- order by email;
- -- -----------------------------------------------------------------
- -- 11.31 Работа с массивами
- drop table if exists log;
- table log;
- create temp table log (
- log_id bigint generated always as identity,
- created_at timestamp not null default current_timestamp,
- messages text not null
- );
- insert into log (created_at, messages) values(
- '2024-08-01 00:47:28.821', 'кажется, всё пропало|или нет, пытаемся восстановить связь|нет, точно всё пропало'
- );
- insert into log (created_at, messages) values(
- '2024-08-01 01:06:21.581', 'id=128|ничоси, опять всё сломалось, никогда такого не было и вот опять'
- );
- select log_id, created_at, (string_to_array(messages, '|'))
- [array_length(string_to_array(messages, '|'), 1)] as last_message
- from log;
- select log_id, created_at,
- split_part(messages, '|', array_length(string_to_array(messages, '|'), 1)) as last_message
- from log;
- select log_id, created_at, split_part(messages, '|', -1) as last_message from log;
- --
- select unnest(string_to_array(messages, '|')) as messages from log;
- select int_array from some_entity where 777=any(int_array);
- select unnest(string_to_array(messages, '|')) from log;
- select unnest as messages from (select unnest(string_to_array(messages, '|')) from log)
- where unnest like '%всё%';
- -- более короткое решение
- select t.* from (
- select unnest(string_to_array(messages, '|') messages
- from log
- ) t where t.messages '%всё%';
- -- -----------------------------------------------------------------
- -- 11.33 Работа с JSON и JSONB
- drop table if exists book_json;
- create temp table book_json (
- book_id bigint generated always as identity primary key,
- data jsonb not null
- );
- -- Данные в поле data (jsonb) могут различаться
- insert into book_json (data) values
- ('{"name": null}'),
- ('{"name": ""}'),
- ('{"name": "Тихий Дон"}'),
- ('{"name": 777}'),
- ('{}');
- table book_json;
- select book_id, data from book_json where data ? 'name';
- select book_id, data from book_json where data->>'name' is not null;
- select book_id, data from book_json where length(data->>'name') > 0;
- -- или вот такой вариант
- select * from book_json
- where data->>'name' is not null and data->>'name' != '';
- -- Создание таблицы с ограничениями по jsonb
- create table book_json(
- book_id bigint generated always as identity primary key,
- data jsonb not null check (
- data->>'name' is not null and
- data->>'pages' is not null and
- (data->>'pages')::int > 0
- )
- );
- -- -----------------------------------------------------------------
- -- 11.33 Изменение структуры таблиц
- -- Добавить ограничение на таблицу
- alter table book_json add check (
- data->>'name' is not null and
- data->>'pages' is not null and
- (data->>'pages')::int > 0
- );
- -- Добавить колонку к таблице
- alter table book_json
- add column created_at timestamp not null default current_timestamp;
- alter table book_json
- add column created_at timestamp not null default now();
- -- -----------------------------------------------------------------
- -- 11.38 INNER JOIN
- table species;
- table genus;
- select species_name as вид, genus_name as род from species
- join genus using(genus_id)
- order by species_name;
- -- Другие условия
- select species_name вид, genus_name род
- from species s join genus g on s.genus = g.genus_id
- order by species_name;
- --
- drop table if exists client, payment cascade;
- create temp table client (
- client_id bigint generated always as identity primary key,
- email varchar(360) not null
- );
- create temp table payment (
- payment_id bigint generated always as identity primary key,
- payment_time timestamp not null default current_timestamp,
- amount int not null check (amount > 0),
- client_id bigint not null references client(client_id)
- );
- insert into client (email) values
- ('client1@mail.ru'),
- ('client2@mail.ru'),
- ('client3@mail.ru');
- insert into payment (payment_time, amount, client_id) values
- ((now() - '1 month'::interval), 10, 1),
- ((now() - '2 month'::interval), 11, 2),
- ((now() - '3 month'::interval), 12, 3);
- select email from client
- join payment using(client_id)
- where payment_time::date + interval '1 month' = current_date
- order by email
- table species;
- table genus;
- table family;
- select s.species_name вид, g.genus_name род
- from species s
- join genus g on s.genus_id = g.genus_id
- order by s.species_name;
- -- -----------------------------------------------------------------
- -- 11.39 LEFT И RIGHT OUTER JOIN
- table species;
- table genus;
- select species_name вид, genus_name род
- from species s left join genus g using(genus_id)
- order by species_name;
- -- -----------------------------------------------------------------
- -- 11.40 FULL OUTER JOIN
- select species_name вид, genus_name род
- from species s full join genus g using(genus_id)
- order by species_name;
- select s.species_name вид, g.genus_name род
- from species s
- full join genus g using(genus_id)
- order by s.species_name;
- -- -----------------------------------------------------------------
- -- 11.44 JOIN LATERAL
- table species;
- table genus;
- table family;
- table observations;
- select
- species_name,
- to_char(last_observation.date, 'DD.MM.YYYY') last_observation
- from species left join lateral (
- select observation_date as date
- from observations
- where observations.species_id = species.species_id
- order by observation_date desc
- limit 1
- ) as last_observation on true
- order by species_name;
- -- -----------------------------------------------------------------
- -- 11.44 SEMI JOIN
- select species_name from species s
- where exists (
- select 1
- from observations o
- where o.species_id=s.species_id
- and extract('year' from observation_date)=2019
- ) order by species_name;
- select observer_name, observation_date
- from observations o, species s, genus g, family f
- where o.species_id = s.species_id and
- s.genus_id = g.genus_id and
- g.family_id = f.family_id and
- f.family_name = 'Синицевые'
- order by observer_name;
- --
- select family_id from family where family_name='Синицевые'
- table genus;
- select genus_id from genus g where exists (
- select 1
- from family f
- where family_name='Синицевые'
- and f.family_id=g.family_id
- );
- select species_id from species s where exists (
- select genus_id from genus g where exists (
- select 1
- from family f
- where family_name='Синицевые'
- and f.family_id=g.family_id
- ) and g.genus_id=s.genus_id
- );
- select observer_name, observation_date from observations o
- where exists (
- select 1 from species s where exists (
- select 1 from genus g where exists (
- select 1
- from family f
- where family_name='Синицевые'
- and f.family_id=g.family_id
- ) and g.genus_id=s.genus_id
- ) and s.species_id = o.species_id
- ) order by observer_name;
- select observer_name, observation_date from observations
- join species s using(species_id)
- join genus g using(genus_id)
- join family f using(family_id)
- where family_name = 'Синицевые'
- order by observer_name;
- -- -----------------------------------------------------------------
- -- Разное
- select div(11, 5);
- select extract(years from '2234-02-23'::date) as year;
- SELECT LENGTH('sql-academy') AS str_length;
|