49. Проектирование таблиц «Продукты» и «Наличие товаров по магазинам» #
Условие задачи:
📌 Необходимо спроектировать структуру таблиц для сети магазинов, чтобы обеспечить:
- Какие товары есть в том или ином магазине.
- В каких магазинах есть тот или иной товар.
- Общее количество каждого товара по всем магазинам.
- Информацию об отсутствующих товарах в конкретном магазине.
Код:
-- Основная таблица магазинов
CREATE TABLE store (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- Таблица товаров
CREATE TABLE product (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
sku TEXT UNIQUE NOT NULL, -- артикул
description TEXT
);
-- Промежуточная таблица наличия товара в магазине
CREATE TABLE store_inventory (
store_id BIGINT NOT NULL
REFERENCES store(id),
product_id BIGINT NOT NULL
REFERENCES product(id),
quantity INT NOT NULL CHECK (quantity >= 0),
PRIMARY KEY (store_id, product_id)
);
Спойлеры к решению
Подсказки
💡 Для связи «многие‑ко‑многим» между магазинами и товарами необходима junction‑таблица
💡 Поле
💡 Уникальный ключ
💡 Таблица
store_inventory
.💡 Поле
quantity
хранит текущее количество единиц товара в каждом магазине (может быть 0).💡 Уникальный ключ
(store_id, product_id)
гарантирует отсутствие дублирующих записей.💡 Таблица
product
содержит sku
(артикул) для внешних интеграций и поиск.Решение
-- Пример наполнения:
INSERT INTO store (name) VALUES ('На опушке'), ('Речной');
INSERT INTO product (name, sku, description)
VALUES
('Хлеб', 'BREAD-001', 'Батон белый'),
('Молоко', 'MILK-001', '2.5% жирности'),
('Яблоки', 'APPLE-001', 'Зеленые');
-- Указываем наличие товаров в магазинах:
INSERT INTO store_inventory (store_id, product_id, quantity)
VALUES
(1, 1, 50), -- в магазине 1 — 50 штук Хлеба
(1, 2, 30), -- в магазине 1 — 30 штук Молока
(2, 2, 0), -- в магазине 2 — нет Молока
(2, 3, 20); -- в магазине 2 — 20 штук Яблок
-- 1) Товары в конкретном магазине:
SELECT p.name, si.quantity
FROM store_inventory si
JOIN product p ON p.id = si.product_id
WHERE si.store_id = 1;
-- 2) Магазины, где есть конкретный товар:
SELECT s.name, si.quantity
FROM store_inventory si
JOIN store s ON s.id = si.store_id
WHERE si.product_id = 2 AND si.quantity > 0;
-- 3) Общее количество товара по всем магазинам:
SELECT p.name,
SUM(si.quantity) AS total_quantity
FROM product p
LEFT JOIN store_inventory si ON si.product_id = p.id
GROUP BY p.name;
-- 4) Список магазинов, где товар отсутствует:
SELECT s.name
FROM store s
LEFT JOIN store_inventory si
ON si.store_id = s.id AND si.product_id = 2
WHERE COALESCE(si.quantity, 0) = 0;