我的 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;
}
}
最佳答案
有一种方法,但它会随着您添加的字段越多而变得越昂贵。许多选择以该形式存储额外用户数据的 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 次这样的连接,然后再一次,我会分析它以确保。
关于php - 高级 MySQL 连接。加速查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8809902/