работа над ошибками по Создание таблиц, JOIN, UNION, Агреции и группировки, Функции, CTE.
This commit is contained in:
+1
-3
@@ -28,12 +28,10 @@ DROP TABLE IF EXISTS mnoskov.orders;
|
|||||||
CREATE TABLE mnoskov.orders (
|
CREATE TABLE mnoskov.orders (
|
||||||
id bigint PRIMARY KEY,
|
id bigint PRIMARY KEY,
|
||||||
user_id bigint,
|
user_id bigint,
|
||||||
order_date date NOT NULL, -- в названии date, и тип думаю date
|
order_date timestamptz NOT NULL, -- в названии date, и тип думаю date
|
||||||
status varchar(20), -- думал лучше int, но судя по заданию DML лучше varchar
|
status varchar(20), -- думал лучше int, но судя по заданию DML лучше varchar
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||||
);
|
);
|
||||||
ALTER TABLE mnoskov.orders
|
|
||||||
ALTER COLUMN order_date TYPE timestamptz;
|
|
||||||
|
|
||||||
|
|
||||||
-- Задание 4
|
-- Задание 4
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ LEFT JOIN
|
|||||||
-- Задание 2
|
-- Задание 2
|
||||||
SELECT
|
SELECT
|
||||||
oi.order_id,
|
oi.order_id,
|
||||||
p.name AS prouct_name,
|
p.name AS product_name,
|
||||||
oi.quantity,
|
oi.quantity,
|
||||||
oi.price_at_purchase
|
oi.price_at_purchase
|
||||||
FROM
|
FROM
|
||||||
@@ -75,7 +75,7 @@ WHERE
|
|||||||
-- Задание 6
|
-- Задание 6
|
||||||
SELECT
|
SELECT
|
||||||
oi.order_id,
|
oi.order_id,
|
||||||
u.id AS user_name,
|
u.id AS user_id,
|
||||||
p.name AS product_name,
|
p.name AS product_name,
|
||||||
oi.quantity
|
oi.quantity
|
||||||
FROM
|
FROM
|
||||||
|
|||||||
@@ -70,6 +70,6 @@ FROM
|
|||||||
mnoskov.products p
|
mnoskov.products p
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
mnoskov.order_items oi ON p.id = oi.product_id
|
mnoskov.order_items oi ON p.id = oi.product_id
|
||||||
WHERE oi.product_id = NULL;
|
WHERE oi.product_id is NULL;
|
||||||
-- Проверка IS NULL по полю из order_items, потому что это права таблица, и null будут добавляться в неё
|
-- Проверка IS NULL по полю из order_items, потому что это права таблица, и null будут добавляться в неё
|
||||||
-- 1) Понизить цену товара 2) лучше прорекламировать 3) снять с продажи
|
-- 1) Понизить цену товара 2) лучше прорекламировать 3) снять с продажи
|
||||||
+2
-2
@@ -93,7 +93,7 @@ HAVING
|
|||||||
count(*) >= 2
|
count(*) >= 2
|
||||||
ORDER BY
|
ORDER BY
|
||||||
active_user_count DESC;
|
active_user_count DESC;
|
||||||
-- is_active = true логичнее писать в HAVING, потому что is_active - не агрегат
|
-- is_active = true логичнее писать в WHERE, потому что is_active - не агрегат
|
||||||
-- Если нет страны где больше двух активных юзеров, то ничего не выведется
|
-- Если нет страны где больше двух активных юзеров, то ничего не выведется
|
||||||
|
|
||||||
|
|
||||||
@@ -126,5 +126,5 @@ HAVING
|
|||||||
sum(quantity * price_at_purchase) < 10000
|
sum(quantity * price_at_purchase) < 10000
|
||||||
ORDER BY
|
ORDER BY
|
||||||
order_revenue;
|
order_revenue;
|
||||||
-- Не понял вопрос: Какие реальные причины могут быть у очень маленьких заказов (1–2 гипотезы)?
|
-- Не понял вопрос: Какие реальные причины могут быть у очень маленьких заказов (1–2 гипотезы)? Ответ: «доставка пробников/тестовой партии», «использование купонов/бонусов», «технический тест витрины»
|
||||||
-- Проще увидеть глазами отфильтрованные микро-заказы
|
-- Проще увидеть глазами отфильтрованные микро-заказы
|
||||||
@@ -40,7 +40,7 @@ FROM
|
|||||||
mnoskov.users
|
mnoskov.users
|
||||||
ORDER BY
|
ORDER BY
|
||||||
age;
|
age;
|
||||||
-- Почему удобнее держать логику сегментации в SQL (CASE), а не только в коде приложения? Я не понял этот вопрос.
|
-- Почему удобнее держать логику сегментации в SQL (CASE), а не только в коде приложения? В каком коде? Если в 'коде приложения' - это какая-то отдельная программа, то могут предположить, чтобы передавать в приложение уже отфильтрованные данные, чтобы задачи базы данных не выносить из базы.
|
||||||
-- Если забыть в ветку ELSE, то будет NULL у тех кто никуда не попал
|
-- Если забыть в ветку ELSE, то будет NULL у тех кто никуда не попал
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ SELECT
|
|||||||
created_at::date,
|
created_at::date,
|
||||||
current_date - created_at::date AS days_since_registration,
|
current_date - created_at::date AS days_since_registration,
|
||||||
CASE
|
CASE
|
||||||
WHEN created_at >= current_date - INTERVAL '30 days' THEN 'hot' ELSE 'regular'
|
WHEN created_at >= current_date - INTERVAL '30 days' THEN 'hot' ELSE NULL
|
||||||
END AS hot_flag
|
END AS hot_flag
|
||||||
FROM
|
FROM
|
||||||
mnoskov.users
|
mnoskov.users
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ WHERE NOT EXISTS (
|
|||||||
WHERE
|
WHERE
|
||||||
u.id = o.user_id
|
u.id = o.user_id
|
||||||
)
|
)
|
||||||
-- Работает быстрее чем NOT IN
|
-- NOT EXISTS безопаснее в плане NULL, и часто планируется лучше чем NOT IN
|
||||||
-- Определить какое количество людей не делают заказы, и кинуть им например купон на скидку на первый заказ
|
-- Определить какое количество людей не делают заказы, и кинуть им например купон на скидку на первый заказ
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ ORDER BY
|
|||||||
|
|
||||||
|
|
||||||
-- Задание 4
|
-- Задание 4
|
||||||
WITH revenue_by_user AS (
|
WITH revenue_user AS (
|
||||||
SELECT
|
SELECT
|
||||||
o.user_id,
|
o.user_id,
|
||||||
sum(oi.quantity * oi.price_at_purchase) AS total_revenue
|
sum(oi.quantity * oi.price_at_purchase) AS total_revenue
|
||||||
@@ -63,19 +63,19 @@ WITH revenue_by_user AS (
|
|||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
u.name,
|
u.name,
|
||||||
rbu.total_revenue
|
ru.total_revenue
|
||||||
FROM
|
FROM
|
||||||
mnoskov.users u
|
mnoskov.users u
|
||||||
JOIN
|
JOIN
|
||||||
revenue_by_user rbu ON u.id = rbu.user_id
|
revenue_user ru ON u.id = ru.user_id
|
||||||
ORDER BY
|
ORDER BY
|
||||||
rbu.total_revenue desc;
|
ru.total_revenue desc;
|
||||||
-- Проще читать когда шаг «посчитать выручку по пользователям» вынесен отдельно
|
-- Проще читать когда шаг «посчитать выручку по пользователям» вынесен отдельно
|
||||||
-- Чтобы избежать дублирования импользуется CTE, а не простой подзапрос
|
-- Чтобы избежать дублирования импользуется CTE, а не простой подзапрос
|
||||||
|
|
||||||
|
|
||||||
-- Задание 5
|
-- Задание 5
|
||||||
WITH revenue_by_product AS (
|
WITH revenue_product AS (
|
||||||
SELECT
|
SELECT
|
||||||
product_id,
|
product_id,
|
||||||
sum(quantity * price_at_purchase) AS product_revenue
|
sum(quantity * price_at_purchase) AS product_revenue
|
||||||
@@ -87,13 +87,13 @@ WITH revenue_by_product AS (
|
|||||||
SELECT
|
SELECT
|
||||||
p.name,
|
p.name,
|
||||||
p.category,
|
p.category,
|
||||||
rbp.product_revenue
|
rp.product_revenue
|
||||||
FROM
|
FROM
|
||||||
mnoskov.products p
|
mnoskov.products p
|
||||||
JOIN
|
JOIN
|
||||||
revenue_by_product rbp ON p.id = rbp.product_id
|
revenue_product rp ON p.id = rp.product_id
|
||||||
ORDER BY
|
ORDER BY
|
||||||
rbp.product_revenue
|
rp.product_revenue
|
||||||
LIMIT 3;
|
LIMIT 3;
|
||||||
-- Сначала удобнее считать агрегаты, чтобы код не выгляжел грооздким и чтобы в нем было легче разобраться
|
-- Сначала удобнее считать агрегаты, чтобы код не выгляжел грооздким и чтобы в нем было легче разобраться
|
||||||
-- Отличае в удобстве чтения и написания. И этот агрегат можно потом ещё и переиспользовать
|
-- Отличае в удобстве чтения и написания. И этот агрегат можно потом ещё и переиспользовать
|
||||||
|
|||||||
Reference in New Issue
Block a user