208 lines
8.4 KiB
SQL
208 lines
8.4 KiB
SQL
-- Задание 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
|
||
*/
|