Всем привет. На сайте стоят анкеты с множеством полей. В одной анкете больше полей, в другой поменьше. Данные всех анкет пишутся в одну таблицу. Как правильно спроектировать такую БД? Сейчас: 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. На сколько правильно будет так спроектировать? Не будут ли тормозить запросы на выборку. Может быть есть еще какие-нибудь способы?
Выборка по отдельным полям в этой анкете будет вестись? Если нет, то на стороне сервера, перед запросом все поля сериализуешь в какой-нибудь JSON и одной текстовой строкой пишешь в какую-нибудь колонку "data", одну-единственную. Все, получили безграничную масштабируемость, которая будет быстро работать. Если же выборка по полям будет-таки осуществляться, то тут все чуть сложнее. Я для подобного проекта использовал следующую архитектуру: Таблица_1 - список пользователей Таблица_2 - список полей/вопросов Таблица_3 - список ответов, где у каждого ответа есть ID пользователя, который его дал и ID вопроса, к которому он относится. Все. Из такой БД ты можешь выбирать любые данные в любой комбинации, влоть до выборки по неполным текстам вопросов. Например, можно посчитать количество людей, скажем, у которых указан "пол - мужской", которые в пятом вопросе ответили "затрудняюсь".
Но можно пойти чуть дальше: 1) Сделать таблицу конфигурационную: "типы полей", в которой перечислить названия полея, тип данных, имя таблицы, колонку где лежит, дополнительные опции, если нужно. 2) Таблицы для данных строковых, даты, числовые, блобы и т.д. 3) Постороение интерфейса форм, сохранение, выборка - скачет от конфигурационной таблицы, где какое поле лежит. Добавить новое значение? определил в таблицу с конфигом и забыл. Про выборки: тормозить не будет примерно такая стркутура работает на базе с примерно 100КК объектов (не MySQL правда, на нем не пробовал, хотя в планах запилить поддержку есть), с опциями от десятка до 40, выборка работает по любой из опций, даты по периодам, но требует уже применения хинтов для sql-оптимизатора.
Ну у меня тоже разные типы вопросов, однострочные, галочки, радиобаттоны, смешанные, и тд и тп. Это уже тонкости конкретной реализации. Это уже автор пусть сам думает. Я ему описал фундамент, целых два. Оба - рабочие варианты. А что на этих фундаментах строить - это уже его дело.
Fell-x27, Ke1eth спасибо за ответы. Вариант с кодированием полей в текстовую строку уже использую, но выборку по ней не сделать. Попробую Ваш второй вариант, Fell-x27
Не могли бы вы написать пример запроса на выборку? Не могу сообразить как сделать выборку по параметрам, при этом с получением данных.
Ды все просто. Вот, например дергаем ответ на конкретный вопрос для конкретного юзера: PHP: select * from `answers` where `question_id` = "твой идентификатор вопроса, который ты, например ранее вытянул" and `user_id` = "идентификатор юзера"; Или там...хз давай дернем почту всех пользователей, которые в графе "возраст" указали число более 20. PHP: select `email` from `users` where `user_id` = (select `user_id` from answers where `answer` > 20 and `question_id`="твой идентификатор вопроса, который ты ранее вытянул"); Или можно без выборки вопросов заранее, через поиск по тексту вопроса: PHP: select `email` from `users` where `user_id` = (select `user_id` from answers where `answer` > 20 and `question_id`= (select `question_id` from `questions` where `question_text` = "Ваш возраст:")); Ну или через like %%, но так лучше не делать, не надежно. В общем, это крайне гибкая хрень, инфа 100%.
Спасибо, но тут в другом суть. Вот что непонятно: Есть таблица с пользователями, вопросами и есть таблица с ответами на вопросы. Что бы нагляднее: 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
Возможно, но вам для этого надо подтянуть SQL. Курите в сторону UNION, либо JOIN, в зависимости от нужного результата.
Согласен, что нужно подтянуть. Но имеет ли вообще смысл делать подобную структуру? Будет ли это выгоднее по сравнении с таблицей с 50+ столбцами, где в 90% случаях будут выводиться все 50+ столбцов данных. И еще касательно последнего вопроса с приведением результата выборки к нужному виду: можете кинуть ссылку на мануал или инфу, где рассказывают именно об этом моменте?
То у вас 50+ столбцов, которые будут задействованы в 90% случаев, то у вас в одной побольше, в другой поменьше да еще и с возможностью расширения. Я не могу за вас проектировать конечную архитектуру. Если анкет будет всего две и они совпадают на 90%, то проще тогда делать таблицу с пачкой столбцов. Я же выше написал, гуглите UNION-ы и JOIN-ы. Вы ведь погуглили, верно? Ведь если бы гуглили, то по первой ссылке нашли бы страницу с документацией, где по-русски написано: А далее синтаксис, примеры и полная исчерпывающая инфа.