2012-01-10 3 views
2

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

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

id|username|... 

completed_form_fields

id|formid|userid|fieldkey|data 

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

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

$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; 
    } 
} 
+1

Не могли бы вы высказать свой код? – bfavaretto

+0

Критерии вашего фильтра должны быть частью предложения WHERE, которое динамически построено из информации в таблице completed_form_fields. Я не могу представить, что вы пытаетесь, но вам также может понадобиться INNER JOIN между таблицами пользователей и complete_form_fields. –

+0

@bfavaretto - добавлен образец моего запроса – kilrizzy

ответ

1

Существует способ, но он получает чем дороже, чем больше вы добавляете поля. То же самое происходит со многими 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 таких объединений, а затем снова, я бы прокомментировал это, чтобы убедиться.

+0

Похоже, как мне это нужно. Я надеялся, что есть волшебное решение, о котором я не знал. Благодаря! – kilrizzy

0
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-indexes

0

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

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 'k1', '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 

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

Смежные вопросы