Расширенное соединение MySQL. Ускорение запроса

У меня есть список пользователей моего приложения php (с использованием codeigniter). Каждый пользователь может заполнить форму размером около 1000 или около того. Структура выглядит примерно так:

пользователи

id|username|... 

completed_form_fields

 id|formid|userid|fieldkey|data 

где полевой ключ является единственным уникальным ключом для этого конкретного поля формы, то есть: «first_name»

У меня есть страница поиска пользователей, где люди могут отфильтровывать определенных пользователей по полям, которые они выбрали (цвет глаз, раса, пол …). Затем мне нужно отобразить эти поля, чтобы я хотел (и в настоящее время) получить такой вывод:

 $filteredmembers = array( [0] = Object( [id] => 1 [username] => kilrizzy ... [fields] => Array( [fname] => Jeff [gender] => Male ... 

В настоящее время мой сценарий, очевидно, ведется с тех пор, как я запрашиваю всех участников, заполнивших эту форму, затем прокручиваю каждый из них, чтобы запросить все их поля. THEN отфильтруйте их исходя из критериев + страница / смещение.

Я знаю, что должен быть способ объединить их в один запрос, я не знаком с

Упрощенная версия моего очень медленного кода:

 function get_members(){ $this->db->select('u.*'); $this->db->from('users AS u'); $query = $this->db->get(); if ($query->num_rows() > 0){ $members = $query->result(); //Get fields from each user foreach($members as $mk => $mv){ $fields = $this->get_form_fields($mv->id,1,true); $members[$mk]->fields = $fields; } return $members; }else{ return false; } } function get_form_fields($uid,$form,$values=false){ $this->db->where('user', $uid); $this->db->where('form', $form); $query = $this->db->get('form_fields'); if ($query->num_rows() > 0){ $result = $query->result(); return $result; }else{ return false; } } 

Есть путь, но он становится дорогим, чем больше вы добавляете поля. То же самое происходит со многими CMS, которые предпочитают хранить дополнительные данные пользователя в этой форме.

Вы можете получить рабочий поиск SQL, используя это:

 SELECT users.*, firstname.data AS firstname, lastname.data AS lastname, eyecolor.data AS eyecolor, FROM users LEFT JOIN completed_form_fields AS firstname ON firstname.userid = users.id AND firstname.fieldkey = "firstname" LEFT JOIN completed_form_fields AS lastname ON lastname.userid = users.id AND lastname.fieldkey = "lastname" LEFT JOIN completed_form_fields AS eyecolor ON eyecolor.userid = users.id AND eyecolor.fieldkey = "eyecolor" WHERE firstname.data LIKE '%searchdata%' OR lastname.data LIKE '%searchdata%' OR eyecolor.data LIKE '%searchdata%' 

Этот метод становится очень большим и дорогим для сервера MySQL, чем больше вы добавляете таблицы. Поэтому я бы порекомендовал не переходить более чем на 10-15 таких объединений, а затем снова, я бы прокомментировал это, чтобы убедиться.

 SELECT u.username, f.formid, f.userid, f.fieldkey, f.data FROM user AS u LEFT JOIN completed_form_fields AS f ON f.userid = u.id you should look at indexing your userid, index(userid), via phpmyadmin or sql file 

MySQL-индексы

Я не уверен, что полностью понимаю проблему. Вы можете использовать один запрос, чтобы получить всех пользователей и все их поля (в основном это то, что предложил Филипп):

 SELECT u.username, f.* FROM user AS u INNER JOIN completed_form_fields AS f ON f.userid = u.id ORDER BY u.id, f.fieldkey 

Чтобы отфильтровать результаты, добавьте предложение WHERE с условиями. Например, чтобы получать данные только из fieldkey s», «k2» и «k3»:

 SELECT u.username, f.* FROM user AS u INNER JOIN completed_form_fields AS f ON f.userid = u.id WHERE f.fieldkey IN ('k1', 'k2', 'k3') ORDER BY u.id, f.fieldkey 

Это то, что вы ищете?