Проектирование базы данных. Вопрос о связи таблиц?

Тема в разделе "PHP", создана пользователем Uglik, 24 янв 2016.

Модераторы: latteo
  1. Uglik

    Uglik

    Регистр.:
    8 окт 2008
    Сообщения:
    350
    Симпатии:
    14
    Здравствуйте.

    Подскажите как правильно соединить таблицы в базах данных. Имеется таблица Users и 3 отдельные таблицы с профилями юзеров. Например: Визажист, парикмахер и стилист. У каждой группы хранятся разные данные с информацией.

    Как я понимаю нужно создать промежуточную таблицу для связи Users->Table->(profile_1, profile_2, profile_3) или проставлять ID каждой таблицы в основной таблице Users.

    При авторизация мы получаем запрос с хранящимся индикатором к какому профилю авторизовался пользователь.


    Например если создать таблицу Users:
    id, email, password, usergroup (1,2,3), profile_id, created_at
    Получается нужно в profile_id подставлять id с разных 3 таблиц и группировать к какому профилю идет обращение через usergroup??

    Я правильно понимаю?
     
    Последнее редактирование: 24 янв 2016
  2. Den1xxx

    Den1xxx

    Moderator
    Регистр.:
    15 янв 2014
    Сообщения:
    279
    Симпатии:
    152
    Я бы создал 3 таблицы. 1 — users, 2 — groups, 3 — usergroups,
    Пользователи
    Код:
    CREATE TABLE `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Номер записи',
      `username` varchar(255) NOT NULL COMMENT 'Имя пользователя',
      `email` varchar(255) NOT NULL COMMENT 'Электропочта',
      `password` varchar(255) NOT NULL COMMENT 'Пароль',
       PRIMARY KEY (`id`)
    )
    
    Группы пользователей, здесь хранятся настройки групп — ид, имя, можно добавить ещё права.
    Код:
    CREATE TABLE `groups` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Номер записи',
      `name` varchar(255) NOT NULL COMMENT 'Имя группы пользователей',
       PRIMARY KEY (`id`)
    )
    
    Наборы групп, в которую входит каждый пользователь
    Код:
    CREATE TABLE `usergroups` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Номер записи',
      `userid` varchar(255) NOT NULL COMMENT 'ID пользователя',
      `groupid` varchar(255) NOT NULL COMMENT 'ID группы пользователей',
       PRIMARY KEY (`id`)
    )
    
    Преимущества:
    1. Легко развивать и добавлять поля — например в группы пользователей добавить права для каждой категории.
    2. Легко делать выборки.
    Недостатки — 3 таблицы.

    Второй вариант.
    Можно сделать в одной, но это не правильно и не расширяемо, хотя и быстро.
    Создать в таблице поле для групп данных и хранить там всё массивом, сохраняя через json
     
    Uglik нравится это.
  3. Горбушка

    Горбушка Ищу её...

    Регистр.:
    2 май 2008
    Сообщения:
    3.387
    Симпатии:
    2.357
    тут всё упирается в данные, которые ты хранишь. Если это телефоны и прочее - достаточно 1 таблицы, добавив в неё поле "тип контакта" и поле с доп. информацией - тут хранить json с данными.
     
    Uglik нравится это.
  4. warg

    warg Постоялец

    Регистр.:
    26 июн 2007
    Сообщения:
    125
    Симпатии:
    139
    ключевой вопрос - количество связей между объектами, то есть в данном случае может ли пользователь быть одновременно и визажистом и стилистом ?
     
    Uglik нравится это.
  5. Den1xxx

    Den1xxx

    Moderator
    Регистр.:
    15 янв 2014
    Сообщения:
    279
    Симпатии:
    152
    При структуре из 3 таблиц — легко. И добавлять новые роли тоже легко.

    Вот именно что я делал именно так. А потом стал вопрос с поиском по данным и оказалось, что это не самый удобный и быстрый вариант.
     
    Последнее редактирование: 29 янв 2016
    Uglik и funnywheel нравится это.
  6. Uglik

    Uglik

    Регистр.:
    8 окт 2008
    Сообщения:
    350
    Симпатии:
    14
    На примере фотографа и клиента. У фотографа будут контактные данные, портфолио, о себе и тд. Клиент будет только ФИО и связь с фотографом.

    В данном случае у фотографа будет профиль достаточно широкий с кучей информации а у клиента по сути только ФИО.

    В таком случае я думаю стоит точно разбить данные таблицы в разные и хранить в каждой таблице профиля id_user, а в основной таблице USERS создать поле с группой (usergroup) и делать пометку кто кому принадлежит.

    В будущем возможно поэтому этот момент тоже хотелось бы предусмотреть.
     
  7. Горбушка

    Горбушка Ищу её...

    Регистр.:
    2 май 2008
    Сообщения:
    3.387
    Симпатии:
    2.357
    Честно говоря, не особо понимаю несколько таблиц с пользователями...
    Пустые колонки есть особо и не просят... Зато поиск облегчается...

    А если человек и клиент, и фотограф? 2 учётки?

    Делай в 1 таблице и не парься... Не популярные поля - выноси в text с json, популярные/большие - в отдельные колонки. Поменять - раз плюнуть.
    Поля "не для всех" можно вынести в доп. таблицу и цеплять через LEFT (RIGHT) JOIN, как у DLE мета-данные к новостям.
     
  8. Uglik

    Uglik

    Регистр.:
    8 окт 2008
    Сообщения:
    350
    Симпатии:
    14

    Получается по структуре это будет выглядеть примерно:

    Таблица USERS (id_user, email, password, token, users_group(enum['admin', 'manager', 'photograf', 'client']), created_at[datetime], updated_at[TIMESTEMP]) для авторизации пользователей и она имеет связь один к одному по внешнему клучу "id_user" с таблицей PROFILES (id_profile, id_user, first_name, last_name, avatar, created_at[datetime], updated_at[TIMSTEMP]) основные столбцы (общие для всех профилей) и дополнительные (id_location, about, start_date, end_date, id_categorie, id_portfolio) для фотографа которые стоит вынести в отдельную таблицу которая будет иметь связь один ко многим с таблицами LOCATIONS, CATEGORIES, PORTFOLIO?

    Получаеться что как то так нужно проектировать базу для юзеров? Под фото создается отдельная таблица PHOTO(id_photo, source, alt, title, view, like, created_at[datetime], updated_at[TIMSTEMP]) и нужно сделать промежуточную таблицу PORTFOLIO (id_profile[int] PK NN, id_photo[int] PK NN, updated_at[TIMESTEMP]) для связи многие ко многим с таблицей PROFILES или лучше связывать с таблицей USERS потому что портфолио принадлежит юзеру-фотографу, а не профилю фотографу? Но как правило таблицам связанным по внешнему ключу присваивается значение NOT NULL но в данной ситуации не у всех профилей будет свою портфолио.

    Подскажите может есть какие то замечания и предложения по данному вопросу как грамотно спроектировать базы данных
     
  9. Uglik

    Uglik

    Регистр.:
    8 окт 2008
    Сообщения:
    350
    Симпатии:
    14
    Спасибо за замечание, не по той ссылке нажал) хотел поставить нравиться!
     
    Den1xxx нравится это.
  10. Горбушка

    Горбушка Ищу её...

    Регистр.:
    2 май 2008
    Сообщения:
    3.387
    Симпатии:
    2.357
    Честно, сейчас не так свободен, чтобы дать тебе конкретику... Дам направление мысли:
    Когда будешь уже реализовывать - задумайся вот над чем... Есть 3 составляющего у БД: Хранение, Вывод и Ввод данных...
    На это и упирайся...

    В 99% случаев, нагрузка возникает именно на уровне ВЫВОДА информации... Поэтому принято жертвовать 1%, повышая объём данных (через некое дублирование или пустые таблицы) искорость/ удобство ВВОДА данных.

    Если у тебя 99% времени данные выводятся из таблицы - делай её такой, чтобы её было БЫСТРО читать. INNER JOIN здесь очень плохой помощник => меньше таблиц = больше скорость... Но часть данных, используемых, к примеру, только в полной новости и не используемая для поиска (к примеру мета-теги, семантика, соцсети и т.д.) можно вынести в отдельную таблицу и цеплять её только в полной новости не через INNER JOIN, а отдельным запросом с конкретным ID строки = меньше нагрузка.

    В общем как-то так... Думай об оптимизации получения данных, немного подзабивая на размер и скорость занесения данных.
     
    Uglik нравится это.