Помощ с дизайн на база данни и примерни заявки

vinsbg

Registered
Здравейте,
трябва ми малко помощ с дизайна на една база данни. Значи имам таблица с Ресторанти с полета id, name, image, text и menu.

Сега искам да направя таблица с менюта - Салати, Напитки, Готвено, Скара, Десерти и т.н.
Всеки ресторант ще си има свое меню с по-горе посочени категории. Как мога да навържа нещата?
Това, което аз се сещам и ми се върти в глава е таблицата 'menu' да съдържа всички артикул и някакво поле, което да показва примерно съответната салата към кой ресторант е ( по ID на ресторанта може би? ). Или нещо такова ..
Други идеи?
И как би изглеждало едно подобно 'навързване'.

Идеята е следната:
Потербителя отваря меню Ресторанти. От там си избира ресторант и трябва да зареди - Салати, Напитки, Готвено, Скара, Десерти и т.н. След това избира примерно Салати и му изкарва салатите само за съответния ресторант, който е избрал.

Колко таблици ще са нужни? Връзки между тях.. полета..
 
Начини бол, въпроса на тебе как ще ти е по-лесно.
Това което си дал като идея е добро и практично.
Аз се сещам и за още няколко начина. Единият начин да си направиш една таблица примерно "menu_type" която ще има 2 полета id,type. Като на type ще сложиш вида на ястието : Салата,Напитка,Готвено ...
След това си правиш една таблица с ястията която ще има, поне, 4 полета за които се сещам, id, menu_type.id,restaurant.id, namе. Като menu_type.id и restaurant_id са FOREIGN KEY и това ще ти е връзката към menu_type за да вземеш вида на ястиетпо(Салата,скара,готвено...) и към ресторанта.

menu_type
|_t_id_|name|
| 1 |Салати |
| | |
| | |
| | |


menu
|_id__|name|__|t_id__|restaurant_id|
| 1 |Шопска| 1 | 1 |
| |салата |
| | |
| | |


Сега, рисунката не е от най-добрите :D , ама дано ти стана ясно.

Другия начин за които се сещам е да направиш таблица за всичко по отделно и после в една да ги навържеш. Т.е таблица Salads(id,name,r_id) и така нататък, другите по същия начин, но това не е най-добрата идея. Много таблици,много заявки,или усложняване на заявка.

Тея два начина се сещам вмомента, ако се сетя и някой друг, ще пиша :)
 
Ако данните ще са много и искаш да избегнеш дублирането им можеш да направиш така:

таблица cats:
id|ime|parent

Въвеждаш основните категории с parent=0, за подкатегориите parent е външен ключ към cats.id
Основните категории извеждаш със SELECT * FROM cats WHERE parent = 0
Самите продукти въвеждаш в отделна таблица

таблица produkti:
id|ime|cat|opisanie|и т.н. полета


свързваща таблица restoranti-produkti:
restorant|produkt|cena

restorant ти е външен ключ към ресторанти.id
produkt ти е външен ключ към produkti.id
в тази таблица освен cena можеш да добавиш и други полета за данни, които се различават в различните ресторанти - грамажи и т.н. (или пък различни грамажи за един и същ продукт в един и същ ресторант, но на различни цени).

Най-важното при проектирането на базата данни е всяка група данни, които са автономни, да са отделени в отделна страница. В противен случай става дублиране и ненужно увеличаване на размера на базата данни. Времето за изпълнение на заявките не трябва да те притеснява - при правилно зададени индекси и InnoDB тип на таблицата е достатъчно бързо
 
Ако помислиш малко се получават нещата. Просто трябва да си подредиш мислите. (същото е като на mapkata, само пояснявам откъде идват нещата) Много е подобно на наследяването в ООП, и понеже видях, че имаш тема за java/android, би трябвало да го разбереш. Представи си всяка таблица като отделен клас/тип, който може да се наследява.

Най-голямото, което имаш са ресторантите. В тях стои всичко останало. Затова имаш една главна таблица restaurants -> id, name, adress, image

Следващото нещо са видовете ястия. Те не наследяват ресторантите, те са отделно от тях. Затова и те са в "главна" таблица - types

Сега имаме таблица меню. Менюто Е ястие, следователно ще "наследи" таблицата (класа) types. В sql "наследяването" (свързването) се прави с допълнително поле, което ще показва id-to на елемента, от който наследяваме. В случая яденетата ще наследят видовете ястия => полето ще е type_id.
Какво още е характерно за всяко меню? То принадлежи към определен ресторант. Затова трябва да имаш едно поле, в което ще записваме ресторанта (неговото id). И така се получават следните колони: id, name, content, type_id, restaurant_id


raiden, не е ли излишна тази свързваща таблица? Не е ли достатъчно в самата таблица produkti да има id към ресторанта? В случая с ресторантите всеки ресторант предлага различни неща, продуктите трудно ще се дублират.
 
Не са чак толкова различни нещата в менютата - там е едното място, където лесно могат да се дублират данни. Другото място, както споменах, е когато един и същ продукт се предлага в различно количество (пр: Пица 15см и 25см; Ориз 300г, 500г и 800г). Ако се използва такава таблица може бързо изведе цялото меню на определен ресторант, може да се изведат други ресторанти, които предлагат същия продукт, да се направи сравнение на цените на продукт в различните ресторанти - плюсовете са много, минуси няма. При подобен обем данни се усеща и разлика в скоростта:
Capture.png

Ако го правя аз ще изнеса дори съставките в отделна таблица, за да мога да търся и по тях
 
Благодаря ви за отговорите. Първо искам да кажа, че базата ще е много малка. Ще съдържа 4 ресторанта, 4-5 главни категории ( напитки, салати, готвено, скара, десерти .. ит .н.) и не голям брой яденета.
По отговора на @mapka7a направих таблиците така.
Таблица 'restaurants', която ще държи ресторантите
Код:
`restaurants` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(403) NOT NULL,
  `menu` varchar(40) NOT NULL,
  `image` varchar(60) NOT NULL,
  `text` text NOT NULL,
  `adress` text NOT NULL,
  PRIMARY KEY (`id`)
Таблица 'meal_types', която ще държи главния вид на яденето
Код:
`meal_types` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
И таблица 'meals', която ще държи всички яденета
Код:
`meals` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `image` varchar(60) NOT NULL,
  `text` text NOT NULL,
  `restaurants.id` int(11) NOT NULL,
  `meal_tyrpes.id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
Така дали са добре? Също така как мога да направя сега `restaurants.id` и `meal_tyrpes.id` FOREIGN KEY. Така, значи `restaurants.id` ще е foreign key на restaurants и `meal_tyrpes.id` ще бъде на таблица `meal_types`.

Също така примерни заявки? Ако потребителя натисне на ресторант 1 и избере салати и след това избере шопска салата и да извади за името, снимката и текста(описанието)?

update:
Аз мисля, че успях да ги направя таблиците
Код:
ALTER TABLE `meals` ADD FOREIGN KEY (`restaurants.id`) REFERENCES `DB`.`restaurants`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; 
ALTER TABLE `meals` ADD FOREIGN KEY (`meal_tyrpes.id`) REFERENCES `DB`.`meals`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
Т.е. сега restaurant.id е FOREIGN KEY на restaurant(id) и meal_type.id на meals(id) ?

update2:
Аз сега се замислих, че те ресторантите ще са различен тип - Индийски, Китайски, Българска кухня и една Пицария. Съответно за всеки ще ми трябва отделно меню, т.е. да асоциирам таблица `restaurants` със някаква таблица, която държи пък менютата. Тази таблица пък с менютата вече да е свързана с типа и вида храна.
Така ли ще трябва да стане.. защото не се сещам как ще стане с текущите таблици..
примерно таблица `menu` с полета id, restaurant.id, meal_types.id ?

Код:
ALTER TABLE `menu` ADD FOREIGN KEY (`restaurant.id`) REFERENCES `DB`.`restaurants`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; 
ALTER TABLE `menu` ADD FOREIGN KEY (`meal_types`) REFERENCES `DB`.`meal_types`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
Нещо такова?
Код:
'шопска салата'(meals(id=1))->'салати'(meal_types(id=1))->'меню 1, което е 'Българска кухня'(id=1)->ресторант 1, който е 'Българска кухня'(id=1).
Горе долу разбрах цялото нещо, но само не разбрах как точно да се разбере кои храни за кой ресторант да излизат.
 
Добре де, menu и meals не е ли една и съща таблица?? :D

Сега се сетих, че всеки ресторант може да иска да има различни категории - в един ще има раздел "пици", в друг няма да има. Така ли е?

Ако е ясно, че всеки ресторант ще има точно определени категории, сега е добре.
В другия случай, ще стане по-гъвкаво, ако имаш свързваща таблица между restaurants и meal_types, която ще показва кой ресторант какви яденета предлага.
Въпросната свързваща таблица ще има само 2 колони - meal_id и restaurant_id. Останалото ще се запази както е в момента.

А за последния ти въпрос - просто една заявка с where?
[sql]select * from meals where restaurant_id = 'избраният ресторант' and meal_type="избраният вид ядене"[/sql]
 
anonimen каза:
Сега се сетих, че всеки ресторант може да иска да има различни категории - в един ще има раздел "пици", в друг няма да има. Така ли е?
Така е. Идеята ми на menu ми беше, че в meals примерно мога да имам още едно поле, което да сочи към menu.id. И от menu вече да се взимат само храни за съответния ресторант, но май няма да е така? :)
:?
 
Всяко ядене принадлежи едновременно към някой ресторант и към вид_ядене. Затова ти казах да направиш свързваща таблица, в която ще има колони meal_id, restaurant_id. Таблица menu няма да е необходима.

И така, в meals ще имаш абсолютно всички яденета. Във meal_type ще имаш всички видове яденета, но няма да се повтарят (няма да имаш веднъж супи за единия ресторант и веднъж за другия). За да определим кой ресторант какви видове ядене предлага, ще се използва свързващата таблица - напр. rest_mealtype. В нея ще записваш кой ресторант какви видове ядене предлага. Така ше си осигуриш възможност за лесно добавяне на видове към даден ресторант.
Получава се тази структура:
Код:
restaurants
id, name

meal_types
id, name

restaurant_mealtype
mealtype_id, restaurant_id

meals
id, name, mealtype_id, restaurant_id
 
anonimen каза:
Всяко ядене принадлежи едновременно към някой ресторант и към вид_ядене. Затова ти казах да направиш свързваща таблица, в която ще има колони meal_id, restaurant_id. Таблица menu няма да е необходима.

И така, в meals ще имаш абсолютно всички яденета. Във meal_type ще имаш всички видове яденета, но няма да се повтарят (няма да имаш веднъж супи за единия ресторант и веднъж за другия). За да определим кой ресторант какви видове ядене предлага, ще се използва свързващата таблица - напр. rest_mealtype. В нея ще записваш кой ресторант какви видове ядене предлага. Така ше си осигуриш възможност за лесно добавяне на видове към даден ресторант.
Получава се тази структура:
Код:
restaurants
id, name

meal_types
id, name

restaurant_mealtype
mealtype_id, restaurant_id

meals
id, name, mealtype_id, restaurant_id
Тази табли restaurant_mealtype не е ли същата, като моето първо предложение - таблица `menu` с полета id, restaurant.id, meal_types.id. :)
Много благодаря за предложението. Няма да мога сега да ги направя и да видя как излизат, че предстои едно пътуване тази вечер и утре.. В Четвъртък ще пиша какъв е резултата. :?:
 
Защо да има свързваща таблица, при положение че връзката си я има в таблицата с ястията?
[sql]SELECT видове.id, видове.име, COUNT(ястия.id) FROM ястия
LEFT JOIN видове ON ястия.вид = видове.id
WHERE ястия.ресторант = №
GROUP BY ястия.вид[/sql]
Ще изведе само видовете, в които има добавени ястия.
 

Back
Горе