· 9 years ago · Dec 15, 2016, 11:56 AM
1SET search_path=public;
2
3/**
4 * Пироговый Ñправочник.
5 *
6 * ПредполгаетÑÑ, что Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¸Ñ€Ð¾Ð³Ð¾Ð² уникальны (их называют поÑетители),
7 * но Ð´Ð»Ñ ÑƒÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ еÑть фиктивные номера. Ð’ÐµÑ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в
8 * килограммах (три знака поÑле запÑтой - граммы), валюта оплаты - только рубли.
9 *
10 * Так как аÑÑортимент менÑетÑÑ, пироги из Ñтарых заказов могут иÑчезнуть, однако
11 * информацию о них терÑть не хочетÑÑ. ПоÑтому пирог можно пометить как "доÑтупный"
12 * или "недоÑтупный" Ð´Ð»Ñ Ð·Ð°ÐºÐ°Ð·Ð°.
13 */
14DROP TABLE IF EXISTS Pies CASCADE;
15CREATE TABLE Pies (
16 Id SERIAL NOT NULL PRIMARY KEY,
17 Title VARCHAR(100) NOT NULL UNIQUE,
18 FullWeightKg DECIMAL(10, 3) NOT NULL CHECK(FullWeightKg > 0),
19 PriceRubPerKg DECIMAL(10, 2) NOT NULL CHECK(PriceRubPerKg > 0),
20 IsOffered BOOLEAN NOT NULL DEFAULT true
21);
22
23/**
24 * Справочник ÑущеÑтвующих ингридиентов.
25 *
26 * Только имена. Каждый ингридиент может ÑчитатьÑÑ Ð² разных единицах в
27 * разных рецептах (штуки шоколадок, граммы шоколада), но на Ñкладе должен
28 * хранитьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в одном виде (либо невÑкрытые пачки, либо Ñуммарный веÑ),
29 * иначе приложениÑм надо будет поÑтоÑнно конвертировать. ПоÑтому имена
30 * уникальны.
31 */
32DROP TABLE IF EXISTS Ingredients CASCADE;
33CREATE TABLE Ingredients (
34 Id SERIAL NOT NULL PRIMARY KEY,
35 Title VARCHAR(100) NOT NULL UNIQUE
36);
37/**
38 * Единицы Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð² ингридиентах пирогов: кг (по маÑÑе), литр (по объёму),
39 * штука.
40 */
41DROP TYPE IF EXISTS AmountUnit CASCADE;
42CREATE TYPE AmountUnit AS ENUM ('кг', 'гр', 'шт');
43
44/**
45 * Ингридиенты пирогов.
46 *
47 * Может потребоватьÑÑ Ð½ÐµÑколько ингридиентов в разных единицах измерениÑ:
48 * 200 грамм Ñблок в теÑто и ещё одно целое Ð´Ð»Ñ ÑƒÐºÑ€Ð°ÑˆÐµÐ½Ð¸Ñ.
49 */
50DROP TABLE IF EXISTS PieComponents CASCADE;
51CREATE TABLE PieComponents (
52 PieId INT NOT NULL REFERENCES Pies,
53 IngredientId INT NOT NULL REFERENCES Ingredients,
54 Amount DECIMAL(10, 3) NOT NULL CHECK(Amount > 0),
55 AmountUnit AmountUnit NOT NULL,
56 PRIMARY KEY (PieId, IngredientId, AmountUnit)
57);
58**
59 * ОÑтатки на Ñкладе.
60 *
61 * Разные вещи может быть удобно мерÑть в разных единицах (литры молока,
62 * килограммы мÑÑа), но ÐºÐ°Ð¶Ð´Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть измерена ровно в одной единице.
63 * Ðули разрешены Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð¾Ñ‰ÐµÐ½Ð¸Ñ ÑƒÑ‡Ñ‘Ñ‚Ð°.
64 */
65DROP TABLE IF EXISTS IngredientsRemaining CASCADE;
66CREATE TABLE IngredientsRemaining (
67 IngredientId INT NOT NULL PRIMARY KEY REFERENCES Ingredients,
68 Amount DECIMAL(10, 3) NOT NULL CHECK (Amount >= 0),
69 AmountUnit AmountUnit NOT NULL
70);
71-- 'Мука', 'Соль', 'Яйцо', 'РиÑ', 'Картофель',
72-- 'Сыр', 'Грибы', 'Яблоки', 'Кролик', 'КапуÑта',
73-- 'МÑÑо', 'БруÑника', 'Корица', 'Бумага'
74
75**
76 * За какой период ÑтатиÑтика.
77 *
78 * ПрÑмо ÑÐµÐ¹Ñ‡Ð°Ñ ÐµÑть только выходные и будни, но еÑли хранить ÑтатиÑтику
79 * в отдельных Ñтроках, то её удобно дополнительно агрегировать
80 * (например, Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑреднеÑÑƒÑ‚Ð¾Ñ‡Ð½Ð°Ñ ÑтатиÑтика получитÑÑ Ñ‡ÐµÑ€ÐµÐ·
81 * MIN и GROUP BY).
82 */
83DROP TYPE IF EXISTS StatsType CASCADE;
84CREATE TYPE StatsType AS ENUM ('holiday', 'business_day');
85
86/**
87 * СтатиÑтика о продажах.
88 *
89 * Ð”Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ пирога и периода еÑть не более одной запиÑи.
90 * Ðули разрешены Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð¾Ñ‰ÐµÐ½Ð¸Ñ ÑкÑпорта из Ñтороннего формата.
91 */
92DROP TABLE IF EXISTS SalesStats CASCADE;
93CREATE TABLE SalesStats (
94 PieId INT NOT NULL REFERENCES Pies,
95 StatsType StatsType NOT NULL,
96 SoldAmount INT NOT NULL CHECK(SoldAmount >= 0),
97 PRIMARY KEY (PieId, StatsType)
98);
99
100-- ('Пирог Ñ Ñ€Ð¸Ñом и Ñйцом', 0.5, 480),
101-- ('Пирог Ñ ÐºÐ°Ñ€Ñ‚Ð¾Ñ„ÐµÐ»ÐµÐ¼, Ñыром и грибами', 1, 640),
102-- ('Пирог Ñ ÐºÑ€Ð¾Ð»Ð¸ÐºÐ¾Ð¼ и грибами', 0.5, 480),
103-- ('Пирог Ñ Ñблоками', 2.0, 400),
104-- ('Пирог Ñ Ñблоками и корицей', 2.0, 400),
105-- ('Пирог Ñ ÐºÐ°Ð¿ÑƒÑтой и бруÑникой', 2.0, 350),
106-- ('Пирожок Ñ ÐºÐ°Ð¿ÑƒÑтой', 0.1, 500),
107-- ('КулебÑка Ñ Ð¼ÑÑом', 1.0, 720));
108--/
109/**
110 * ПоÑтоÑнные клиенты.
111 *
112 * У каждого еÑть уникальный номер и неуникальное Ð¸Ð¼Ñ (название организации,
113 * имÑ-фамилиÑ, ник). Скидка бывает нулеваÑ, чтобы можно было давать
114 * поÑтоÑнным клиентам какие-то ещё бонуÑÑ‹, кроме денежных.
115 */
116DROP TABLE IF EXISTS Customers CASCADE;
117CREATE Table Customers (
118 Id SERIAL NOT NULL PRIMARY KEY,
119 Name VARCHAR(100) NOT NULL,
120 DiscountPercent INT NOT NULL CHECK(DiscountPercent BETWEEN 0 AND 100)
121);
122/**
123 * Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð·Ð°ÐºÐ°Ð·Ð°.
124 */
125DROP TYPE IF EXISTS OrderStatus CASCADE;
126CREATE TYPE OrderStatus AS ENUM ('received', 'processing', 'shipped', 'completed');
127
128/**
129 * Мелкооптовые заказы.
130 *
131 * У каждого еÑть уникальный номер, ожидаемое Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾Ñтавки (Ñ TZ,
132 * чтобы поменьше завиÑеть от переводов чаÑов), Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ñтавки, ÑтатуÑ.
133 * Также может быть Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ (может не быть, еÑли доÑтавка на Reception),
134 * и может быть номер поÑтоÑнного покупателÑ.
135 */
136DROP TABLE IF EXISTS BatchOrders CASCADE;
137CREATE Table BatchOrders (
138 Id SERIAL NOT NULL PRIMARY KEY,
139 Customer INT NULL REFERENCES Customers,
140 ExpectedDelivery TIMESTAMP NOT NULL,
141 ReceiverName TEXT NULL,
142 Address TEXT NULL,
143 Status OrderStatus NOT NULL
144);
145WITH Ids AS(
146 SELECT generate_series(1, 200) AS id
147), BO AS (
148 SELECT id,
149 (0.5 + random() * (SELECT COUNT(*) FROM Customers))::int AS customer_id,
150 timestamp '2016-06-01' + random() * interval '180 days' AS delivery_time
151 FROM Ids
152)
153/**
154 * СоÑтав заказов.
155 */
156DROP TABLE IF EXISTS BatchOrderPies CASCADE;
157CREATE TABLE BatchOrderPies (
158 BatchOrderId INT NOT NULL REFERENCES BatchOrders,
159 PieId INT NOT NULL REFERENCES Pies,
160 Amount INT NOT NULL CHECK(Amount > 0),
161 PRIMARY KEY(BatchOrderId, PieId)
162);