За последние 24 часа нас посетили 22820 программистов и 1261 робот. Сейчас ищут 733 программиста ...

Проектирование бд

Тема в разделе "MySQL", создана пользователем MasterDmx, 7 сен 2016.

  1. MasterDmx

    MasterDmx Активный пользователь

    С нами с:
    17 авг 2014
    Сообщения:
    31
    Симпатии:
    0
    Всем привет.
    На сайте стоят анкеты с множеством полей. В одной анкете больше полей, в другой поменьше. Данные всех анкет пишутся в одну таблицу. Как правильно спроектировать такую БД?

    Сейчас:
    id | form | name | phone | region | city | zalog .... + еще штук 20 полей

    Суть в том, что если мы внедрим еще поля в анкету, то соответственно придется добавлять еще столбцы в таблицу.

    Пришла в голову идея разделить БД на 2. То есть будет leads и fields.

    leads:
    id | form | phone | region | city

    fields:
    id | leadid | field | value
    ------------------------------
    1 | 1 | zalog | 1
    2 | 1 | summ | 100000


    Таким образом каждая строка будет соответствовать полю и его значению и привязана к таблице leads.

    На сколько правильно будет так спроектировать? Не будут ли тормозить запросы на выборку. Может быть есть еще какие-нибудь способы?
     
  2. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Выборка по отдельным полям в этой анкете будет вестись? Если нет, то на стороне сервера, перед запросом все поля сериализуешь в какой-нибудь JSON и одной текстовой строкой пишешь в какую-нибудь колонку "data", одну-единственную. Все, получили безграничную масштабируемость, которая будет быстро работать.

    Если же выборка по полям будет-таки осуществляться, то тут все чуть сложнее. Я для подобного проекта использовал следующую архитектуру:
    Таблица_1 - список пользователей
    Таблица_2 - список полей/вопросов
    Таблица_3 - список ответов, где у каждого ответа есть ID пользователя, который его дал и ID вопроса, к которому он относится.

    Все. Из такой БД ты можешь выбирать любые данные в любой комбинации, влоть до выборки по неполным текстам вопросов. Например, можно посчитать количество людей, скажем, у которых указан "пол - мужской", которые в пятом вопросе ответили "затрудняюсь".
     
  3. Ke1eth

    Ke1eth Активный пользователь

    С нами с:
    16 мар 2012
    Сообщения:
    1.073
    Симпатии:
    11
    Адрес:
    заблудилса
    Но можно пойти чуть дальше:
    1) Сделать таблицу конфигурационную: "типы полей", в которой перечислить названия полея, тип данных, имя таблицы, колонку где лежит, дополнительные опции, если нужно.
    2) Таблицы для данных строковых, даты, числовые, блобы и т.д.
    3) Постороение интерфейса форм, сохранение, выборка - скачет от конфигурационной таблицы, где какое поле лежит.

    Добавить новое значение? определил в таблицу с конфигом и забыл.
    Про выборки: тормозить не будет примерно такая стркутура работает на базе с примерно 100КК объектов (не MySQL правда, на нем не пробовал, хотя в планах запилить поддержку есть), с опциями от десятка до 40, выборка работает по любой из опций, даты по периодам, но требует уже применения хинтов для sql-оптимизатора.
     
  4. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Ну у меня тоже разные типы вопросов, однострочные, галочки, радиобаттоны, смешанные, и тд и тп. Это уже тонкости конкретной реализации. Это уже автор пусть сам думает. Я ему описал фундамент, целых два. Оба - рабочие варианты. А что на этих фундаментах строить - это уже его дело.
     
  5. MasterDmx

    MasterDmx Активный пользователь

    С нами с:
    17 авг 2014
    Сообщения:
    31
    Симпатии:
    0
    Fell-x27, Ke1eth спасибо за ответы.

    Вариант с кодированием полей в текстовую строку уже использую, но выборку по ней не сделать. Попробую Ваш второй вариант, Fell-x27
     
  6. MasterDmx

    MasterDmx Активный пользователь

    С нами с:
    17 авг 2014
    Сообщения:
    31
    Симпатии:
    0
    Не могли бы вы написать пример запроса на выборку? Не могу сообразить как сделать выборку по параметрам, при этом с получением данных.
     
  7. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Ды все просто. Вот, например дергаем ответ на конкретный вопрос для конкретного юзера:
    PHP:
    1. select * from `answers`
    2.     where `question_id` = "твой идентификатор вопроса, который ты, например ранее вытянул"
    3.         and `user_id` = "идентификатор юзера";
    Или там...хз давай дернем почту всех пользователей, которые в графе "возраст" указали число более 20.
    PHP:
    1. select `email` from `users`
    2.     where `user_id` = (select `user_id` from answers
    3.                                   where `answer` > 20
    4.                                   and `question_id`="твой идентификатор вопроса, который ты ранее вытянул");
    Или можно без выборки вопросов заранее, через поиск по тексту вопроса:

    PHP:
    1. select `email` from `users`
    2.     where `user_id` = (select `user_id` from answers
    3.                                     where `answer` > 20
    4.                                       and `question_id`= (select `question_id` from `questions`
    5.                                                                         where `question_text` = "Ваш возраст:"));
    Ну или через like %%, но так лучше не делать, не надежно.
    В общем, это крайне гибкая хрень, инфа 100%.
     
  8. MasterDmx

    MasterDmx Активный пользователь

    С нами с:
    17 авг 2014
    Сообщения:
    31
    Симпатии:
    0
    Спасибо, но тут в другом суть.

    Вот что непонятно:

    Есть таблица с пользователями, вопросами и есть таблица с ответами на вопросы.
    Что бы нагляднее:
    users
    id | name
    1 | Василий
    2 | Олег
    3 | Петр

    quest
    id | name | altname
    1 | Сумма | summ
    2 | Срок | term
    3 | Возраст | age

    answer
    id | userid | questid | val
    1 | 1 | 1 | 20000
    2 | 1 | 2 | 32
    3 | 2 | 1 | 13000
    4 | 3 | 1 | 420000
    5 | 3 | 2 | 196
    6 | 3 | 3 | 42
    Суть в том, что нужно иметь возможно выбрать тех пользователей, у которых к примеру сумма меньше 10000 И при этом срок больше 30. При этом параметров может быть море.
    А так же при этом получить все имеющиеся данные для этих пользователей (срок, сумму, возраст), в общем все параметры, что есть.

    Возможно ли привести результат выборки к виду:
    id | summ | term | age
    1 | 20000 | 32 |
    2 |13000 | |
    3 | 420000 | 196 | 42
     
  9. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Возможно, но вам для этого надо подтянуть SQL.
    Курите в сторону UNION, либо JOIN, в зависимости от нужного результата.
     
  10. MasterDmx

    MasterDmx Активный пользователь

    С нами с:
    17 авг 2014
    Сообщения:
    31
    Симпатии:
    0
    Согласен, что нужно подтянуть.
    Но имеет ли вообще смысл делать подобную структуру? Будет ли это выгоднее по сравнении с таблицей с 50+ столбцами, где в 90% случаях будут выводиться все 50+ столбцов данных.

    И еще касательно последнего вопроса с приведением результата выборки к нужному виду: можете кинуть ссылку на мануал или инфу, где рассказывают именно об этом моменте?
     
  11. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    То у вас 50+ столбцов, которые будут задействованы в 90% случаев, то у вас в одной побольше, в другой поменьше да еще и с возможностью расширения. Я не могу за вас проектировать конечную архитектуру. Если анкет будет всего две и они совпадают на 90%, то проще тогда делать таблицу с пачкой столбцов.

    Я же выше написал, гуглите UNION-ы и JOIN-ы. Вы ведь погуглили, верно? Ведь если бы гуглили, то по первой ссылке нашли бы страницу с документацией, где по-русски написано:

    А далее синтаксис, примеры и полная исчерпывающая инфа.