Merge branch 'main' into vberetar_sql_join

This commit is contained in:
2026-05-28 20:03:05 +04:00
92 changed files with 10034 additions and 9 deletions
+38
View File
@@ -0,0 +1,38 @@
CREATE TABLE users (
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age SMALLINT CHECK (age > 0),
email VARCHAR(100) NOT NULL UNIQUE,
country VARCHAR(50),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ NOT NULL
);
-- age - для возраста не нужны болшие числа
-- country - можно было бы использовать VARCHAR(2), я бы тут спросил у тимлида как будет удобней использовать поле)
-- created_at - нужно знать не только дату но и время создания/регистрации
-- id - если не прописать not null в primary key, то not null ставится автоматически?
CREATE TABLE products (
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(100) NOT NULL,
category VARCHAR(50),
price DECIMAL(10, 2) NOT NULL,
in_stock BOOLEAN DEFAULT true,
);
CREATE TABLE orders(
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
user_id INT,
order_date TIMESTAMPTZ NOT NULL,
status VARCHAR(20),
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- status - лучше прописать словами статус, так понятней будет. Я бы сюда поставил ENUM
CREATE TABLE order_items(
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
price_at_purchase DECIMAL(10, 2) NOT NULL,
PRIMARY KEY (order_id, product_id)
);
+41
View File
@@ -0,0 +1,41 @@
INSERT INTO users (name, age, email, country, is_active, created_at)
VALUES ('Alice', 25, LOWER('alice@example.com'), 'US', true, '2024-01-10 10:00:00'),
('Bob', 30, LOWER('bob@example.com'), 'UK', true, '2024-02-05 09:30:00'),
('Carol', 27, LOWER('carol@example.com'), 'US', false, '2024-03-01 15:20:00'),
('Diana', 22, LOWER('diana@GMAIL.com'), 'US', true, '2024-01-12 08:15:00'),
('Evan', 35, LOWER('EVAN@example.com'), 'UK', true, '2024-01-18 19:40:00'),
('Farida', 29, LOWER('farida@example.com'), 'KZ', true, '2024-02-20 11:05:00'),
('George', 31, LOWER('george+test@example.com'), 'US', true, '2024-03-05 16:45:00'),
('Ivan', 26, LOWER('ivan@example.com'), 'RU', true, '2024-01-11 14:30:00'),
('Julia', 28, LOWER('julia@example.com'), 'US', true, '2024-03-07 18:05:00');
INSERT INTO products (name, category, price, in_stock)
VALUES ('iPhone 15', 'Электроника', 80000, true),
('Kindle', 'Электроника', 15000, true),
('Кроссовки Nike', 'Одежда', 9000, true),
('Кроссовки NoName', 'Одежда', 3000, false),
('Наушники Pro', 'Электроника', 12000, true),
('Фитнес‑браслет', 'Гаджеты', 6000, true),
('Подарочная карта', 'Сервисы', 1000, true);
INSERT INTO orders (user_id, order_date, status)
VALUES (1, '2025-01-10 12:00:00', 'paid'),
(3, '2025-01-12 09:30:00', 'cancelled'),
(1, '2025-01-15 18:20:00', 'paid'),
(2, '2025-01-20 11:05:00', 'created'),
(4, '2025-02-01 17:45:00', 'paid'),
(5, '2025-02-10 10:10:00', 'refunded'),
(7, '2025-03-01 09:00:00', 'paid'),
(9, '2025-03-05 19:30:00', 'paid');
INSERT INTO order_items (order_id, product_id, quantity, price_at_purchase)
VALUES (1, 1, 1, 78000),
(1, 3, 2, 8500),
(2, 2, 1, 14000),
(3, 5, 1, 11000),
(3, 7, 1, 1000),
(4, 2, 1, 15000),
(5, 6, 1, 6000),
(6, 1, 1, 82000),
(7, 3, 1, 9000),
(8, 4, 2, 2800);
+56
View File
@@ -0,0 +1,56 @@
-- Задача 1
SELECT name, category, price,
price * 1.3 AS price_with_markup,
price * 1.5 AS price_with_vat
FROM products
WHERE (price BETWEEN 100 AND 1300)
AND category NOT IN ('smartwatch')
AND in_stock = TRUE;
-- Вопрос:
-- Что лучше читается BETWEEN 100 AND 1300 или price >= 100 AND price <= 1300 и почему?
-- Ответ:
-- Для меня BETWEEN 100 AND 1300 читается лучше, сразу понятен срез от 100 и 1300.
-- Задача 2
SELECT name, price,
price * 0.85 AS price_with_discount
FROM products
WHERE (price < 100 OR price > 1000);
-- Вопрос:
-- Почему важно явно писать скобки в условии с OR, даже если кажется, что и так понятно?
-- Ответ:
-- Потому что условие может не правильно отобразить результат, AND выполняется раньше OR.
-- Для надежности лучше скобками прописывать явно.
-- Задача 3
SELECT id, name, category, price
FROM products
WHERE price >= 100
AND category IN ('tablet', 'smartphone', 'mouse')
ORDER BY price DESC;
-- Задача 4
SELECT name, category, price
FROM products
WHERE name NOT LIKE '%iPhone%';
-- Задача 5
SELECT name, category, price
FROM products
WHERE name ILIKE '%pro%';
SELECT name, category, price
FROM products
WHERE name ILIKE '%mx%'
ORDER BY price DESC;
-- Вопрос:
-- В одном предложении объясни, почему для поисковой строки лучше ILIKE '%pro%', а не = 'Pro'.
-- Ответ:
-- В названии товаров могут быть буквы (в словах) с разными регистрами, при поиске клиенту можен не показать часть товаров только потому что слово выглядить так - PRO а не так - Pro.
+73
View File
@@ -0,0 +1,73 @@
-- Задание 1
SELECT id, name, country, created_at, email
FROM users
ORDER BY created_at DESC, name;
-- Почему выбрал именно эти столбцы и зачем такая сортировка?
-- Ответ на вопрос:
-- Эти столбцы нужны для анализа пользователей, для тех же аналитиков.
-- Сортировка по дате и имени, я так предпологаю, нужня для удобства.
-- Задание 2
-- Запрос 1
SELECT id, name, country
FROM users
WHERE country = 'US'
ORDER BY name;
-- Запрос 2
SELECT id, name, country
FROM users
WHERE country = 'UK'
ORDER BY name;
-- Какой из двух запросов маркетологу полезнее и почему?
-- Ответ на вопрос:
-- Я так понимаю маркетологу нужно понять какое кол-во пользователей в каждой из стран зарегестрировалось в приложении.
-- Возможно для понимания продвижения продукта и насколько успешна маркетинговая стратегия. И в дальнейшем её корректировка.
-- Задание 3
-- Запрос 1
SELECT id, name, email
FROM users
WHERE email IS NOT NULL -- я знаю что email и так должен быть NOT NULL по DDL, но на всякий прописал
ORDER BY name;
-- Запрос 2
SELECT DISTINCT LOWER(email) as email_lower
FROM users
WHERE email IS NOT NULL;
-- Зачем вообще приводить email к одному регистру и убирать дубликаты на стороне базы?
-- Ответ на вопрос:
-- Приводить email к нижнему регистру необходимо для того чтобы небыло дубликатов почты.
-- После гугления я узнал что в почтовых адресах могут допускаться верхние регистры букв, только потом создать email с теми же буквами но в нижнем регистре нельзя будет, они будут считаться индентичными.
-- Получается несколько пользователей могут залогинится под одним и тем же email адресом но с разными регистрами. А такое нельзя допускать.
-- Для рассылки дубликаты нужно убирать что-бы не приходила рассылка дважды в один и тот же email.
-- Задание 4
-- Запрос 1
SELECT id, name, created_at
FROM users
WHERE created_at > '2024-01-14'
ORDER BY created_at DESC;
-- Запрос 2
SELECT id, name, created_at
FROM users
WHERE created_at > '2024-01-14'
ORDER BY created_at DESC
LIMIT 3;
-- Запрос 3
SELECT id, name, created_at
FROM users
WHERE created_at > '2024-01-14'
ORDER BY created_at DESC
OFFSET 1 LIMIT 2;
-- В каком реальном сценарии тебе пригодится OFFSET?
-- Ответ на вопрос:
-- Не знаю, возможно понадобится посмотреть несколько записей из середины списка.