Files
homework/dmezentsev/postgresql/homework/JOIN.sql
T
2026-05-19 10:39:11 +03:00

208 lines
8.4 KiB
SQL
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Задание 1: Заказы + кто заказал
SELECT u.name AS user_name,
u.country,
o.id AS order_id,
o.order_date,
o.status
FROM dmezentsev.users u
LEFT JOIN dmezentsev.orders o ON o.user_id = u.id;
SELECT u.name AS user_name,
u.country,
o.id AS order_id,
o.order_date,
o.status
FROM dmezentsev.users u
JOIN dmezentsev.orders o ON o.user_id = u.id;
/* - С какой таблицы логичнее начать: orders или users? Почему?
Логичнее начать с таблицы users. А дальше вариантами джойна выбирать, что
нужно: если оставить только тех пользователей, у которых был хотя бы один заказ,
то использовать INNER JOIN. Если вывести так же пользователей, у которых заказа
не было, то LEFT JOIN
- Какой тип JOIN здесь уместнее: INNER или LEFT? Напиши запрос в обоих вариантах и посмотри,
где пропадут строки.
При INNER JOIN пропадут три строки с пользователями, у которых не было ни одного заказа
*/
-- Задание 2: Чек одного заказа
SELECT oi.order_id,
p.name AS product_name,
oi.quantity,
oi.price_at_purchase
FROM dmezentsev.order_items oi
JOIN dmezentsev.products p ON oi.product_id = p.id
WHERE oi.order_id = 101;
/* - Что изменится, если эту фильтрацию order_id = 101 перенести в JOIN (после ON)?
При использовании INNER JOIN оба варианта (WHERE order_id = 101 или
перенести в JOIN (после ON)) дадут одинаковый результат.
Но:
LEFT JOIN dmezentsev.products p ON oi.product_id = p.id
WHERE oi.order_id = 101
Сначала делается джойн, потом фильтруются данные по условию. Вернутся строки,
удовлетворяющие условию фильтрации
LEFT JOIN dmezentsev.products p ON oi.product_id = p.id AND oi.order_id = 101
Тут возможно будет больше строк, так как вернутся строки из order_items c NULL
в таблице products
*/
-- Задание 3: Полный чек по всем заказам
SELECT o.id AS order_id,
u.name AS user_name,
p.name AS product_name,
oi.quantity,
oi.price_at_purchase
FROM dmezentsev.orders o
JOIN dmezentsev.users u ON o.user_id = u.id
JOIN dmezentsev.order_items oi ON o.id = oi.order_id
JOIN dmezentsev.products p ON oi.product_id = p.id;
/* - почему после JOIN заказ 3 появляется в нескольких строках?
Заказ 3 появился в двух строках, потому что при джойне кол-во строк может
увеличиваться. Это связано с тем, что в этом заказе было два наименования,
отсюда и увеличение строк
- Чем результат отличается от задания 2 (по количеству строк и информации)?
В этом запросе строк и информации больше, потому что информация запрошена
по всему магазину, а не по конкретному заказу 101
*/
-- Задание 4: Все пользователи + их заказы (включая тех, у кого заказов нет)
SELECT u.name AS user_name,
o.id AS order_id,
o.status
FROM dmezentsev.users u
LEFT JOIN dmezentsev.orders o ON u.id = o.user_id;
/* - Чем этот запрос отличается от такого же, но с INNER JOIN?
Если бы тут был INNER JOIN, то пользователи без заказов не попали бы в
результирующую таблицу
*/
-- Задание 5: Пользователи без заказов
SELECT u.id AS user_id,
u.name AS user_name
FROM dmezentsev.users u
LEFT JOIN dmezentsev.orders o ON u.id = o.user_id
WHERE o.id IS NULL;
/* - Почему тут важно фильтровать именно по колонке из **`orders`**, а не из **`users`**?
Фильтрую по полю orders.id, потому что это первичный ключ таблицы,
который подразумевает собой факт покупки. То есть если после джойна
это поле IS NULL, то у пользователя не было ни одного заказа
*/
-- Задание 6: Заказы, где есть Kindle
SELECT o.id AS order_id,
u.name AS user_name,
p.name AS product_name,
oi.quantity
FROM dmezentsev.orders o
JOIN dmezentsev.users u ON o.user_id = u.id
JOIN dmezentsev.order_items oi ON o.id = oi.order_id
JOIN dmezentsev.products p ON oi.product_id = p.id
WHERE p.name LIKE '%Kindle%';
-- Задание 7: Товары и в каких заказах они покупались
SELECT p.name AS product_name,
oi.order_id,
oi.quantity
FROM dmezentsev.products p
LEFT JOIN dmezentsev.order_items oi ON p.id = oi.product_id;
/* - Что будет в order_id, если товар ни разу не покупали?
Если бы товар не был ни разу куплен, то в поле order_id был NULL
из-за использования LEFT JOIN
- Чем это отличается от варианта, если использовать INNER JOIN?
При использовании INNER JOIN товар, который ни разу не заказывали,
не попал бы в итоговую таблицу
*/
-- Задание 8: Только оплаченные заказы + их состав
SELECT o.id AS order_id,
u.name AS user_name,
p.name AS product_name,
oi.quantity,
oi.price_at_purchase
FROM dmezentsev.orders o
JOIN dmezentsev.users u ON o.user_id = u.id
JOIN dmezentsev.order_items oi ON o.id = oi.order_id
JOIN dmezentsev.products p ON oi.product_id = p.id
WHERE o.status = 'paid';
SELECT o.id AS order_id,
u.name AS user_name,
p.name AS product_name,
oi.quantity,
oi.price_at_purchase
FROM dmezentsev.orders o
JOIN dmezentsev.users u ON o.user_id = u.id AND o.status = 'paid'
JOIN dmezentsev.order_items oi ON o.id = oi.order_id
JOIN dmezentsev.products p ON oi.product_id = p.id;
/* - Что будет, если условие status = 'paid' написать
в JOIN с orders (там же, где ON)? Изменится ли результат сейчас и почему?
Результат будет один и тот же, потому что используется INNER JOIN.
Строки по условию o.status = 'paid' отсекутся в любом случае, что
при WHERE, что на шаге JOIN
*/
-- Задание 9: Заказы пользователя Alice
SELECT o.id AS order_id,
o.order_date,
p.name AS product_name,
oi.quantity,
oi.price_at_purchase
FROM dmezentsev.orders o
JOIN dmezentsev.users u ON o.user_id = u.id
JOIN dmezentsev.order_items oi ON o.id = oi.order_id
JOIN dmezentsev.products p ON oi.product_id = p.id
WHERE u.name = 'Alice';
/* - Если у Alice нет ни одного заказа, сколько строк вернёт твой запрос и почему?
Если бы у Alice не было заказов, то запрос не вернул ничего, так как
не было бы ни одной строки, удовлетворяющей условию фильтрации
*/
-- Задание 10: Заказы без товаров
SELECT
o.id AS order_id,
o.user_id,
o.status
FROM dmezentsev.orders o
LEFT JOIN dmezentsev.order_items oi ON o.id = oi.order_id
WHERE oi.order_id IS NULL;
/* - Что будет, если вместо LEFT JOIN написать INNER JOIN — изменится ли результат и как?
Если изменить LEFT JOIN на INNER JOIN, то результирующих строк вообще не будет.
INNER JOIN оставит только те заказы, у которых есть хотя бы одна запись в order_items.
То есть при INNER JOIN колонка oi.order_id никогда не будет NULL
*/