Делаю игровой портал, и прошу совета как правильно сделать БД для выборки жанров игр. Сайт делится на n количество платформ и в каждой платформе m жанров. Проблема в динамическом построении структуры меню с жанрами. Одна и та же игра может быть на разных платформах, если игры нет на какой-то платформе, то в этой платформе не нужно выводить название жанры, если игр таких нет.
Я создал таблицу с платформами и жанрами, в которую пишу сколько игр относиться к каждому жанру данной к данной платформе. Но возникает трудность учета при редактировании данных о игре. Если мы удаляем жанр из игры или просто обновляем, то нужно перед изменением проверять данный и решать, добавлять или удалять данные из таблицы жанров.
Может есть более красивый способ решить данную задачу?
По такой базе можно собирать любую статистику, главное не забывать каскадно удалять(например при удалении Игры, нужно удалить все записи из Таблица_Игра_Жанр и Таблица_Игра_Платформа, в которых id_игры совпадает с тем что мы удаляем)
До такой логике я додумался, просто при этом будет занимать значительное время формирования меню.
Пока пройдет по каждой игре, заглянет в таблицу платформы, затем в жанр. Для этого я сделал отдельно таблицу в которой связь платформы с жанрами, и из нее формируется меню.
id | platform_id | Word_games | Puzzle
1 1 1 0
2 2 0 1
Тогда заполнение меню нужными жанрами происходит быстро.
Первое: вам нужно правильно хранить данные, иначе потом где-то потеряете единицу и не восстановите что и как.
Я так понимаю база у вас правильно спроектирована, вы можете по ней определить к каким жанрам каждая игра относится и к каким платформам - проблема с меню.
Второе: перформанс. Очень часто(почти всегда) "красивая" схема и требования не совпадают, для этого можно использовать (начну с неинтересного):
а) оптимизировать запросы (в нашем случае мимо)
б) кешировать на уровне сервера, например nginx : habrahabr.ru/post/163847
в) кешировать на уровне приложения, например memcached : habrahabr.ru/post/108274
г) кешировать на уровне базы данных, например, используя Prepared Statement-ы ( запросы с '?' вместо переменных), но это я для Oracle знаю, что лечит, для вашей СУБД гуглите. Первый запрос на меню отработает скажем 10 секунд, а второй 0.32 секунды (т.к. кеш базы).
д) сделать матвьюшку (будет выглядеть как таблица типа вашей), и туда сливать данные. По сути путь что вы выбрали(почти).
Давайте думать дальше. Выберем пункт Д.
Что должно быть в вашем меню (минимум):
Название пункта
Ссылка
Родительский пункт(если есть)
так давайте именно такую таблицу и строить.
Таблица_Большое_Жанровое_Меню : id | name | anchor | parent_id
По такой таблице можно построить вообще любое меню, и кверя будет шустро бегать.
Если хотите закрепить данные за каждым пунктом, то я бы добавил еще одну колонку с json сериализованным объектом (если по этим данным не будет поиска и вставлять вы будете в PHP или ваша СУБД поддерживает JSON)
Таблица_Большое_Жанровое_Меню : id | name | anchor | parent_id | statistics_json
Ну или опять же делаем еще одну сущность (а что вы хотели то с реляционной то моделью :) ), обозвем ее:
Таблица_Меню_Опции: id | id_пункта_меню | key | value_1 | value_2
я более ли менее дженерик вещи пишу , можно сразу
Таблица_Меню_Статистика: id | id_пункта_меню | type | name | count
types = ['genre', 'platform']
name= 'PC', 'Puzzle', 'Xbox', ...
Написал много, вы найдите что вам по душе из этого и двигайтесь. Надеюсь помог.
Ihor Kalashnikov: Спасибо! Развернутый ответ) Я как раз таки и думал сделать еще одно поле для данных массива, и в массив писать id игр и при изменении уже перебирать массив и изменять, добавлять или удалять. При работе в админке сайта, пару секунд задержки на обработку я думаю, это не критично.