Расширенное соединение MySQL. Ускорение запроса - PullRequest
2 голосов
/ 11 января 2012

У меня есть список пользователей в моем приложении 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
        ...

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

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

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

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;   
    }
}

Ответы [ 3 ]

1 голос
/ 11 января 2012

Есть способ, но он становится дороже, чем больше вы добавляете поля. То же самое происходит со многими 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 голосов
/ 11 января 2012

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

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

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

0 голосов
/ 11 января 2012
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-индексы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...