我的数据库(简化)
inv_assets
| id | manufacturer | type | description
| 1 | HP | 1 | random string
| 2 | Dell | 4 | test string
inv_location
| id | asset_id | building | room | user | date_moved
| 1 | 1 | main | 100 | John | 2014-04-01
| 2 | 1 | main | 102 | Henry| 2014-04-20
| 3 | 2 | remote | 200 | Beth | 2014-05-01
| 4 | 2 | main | 105 | Jim | 2014-05-30
项目表中的每个项目在位置表格中都有多个位置,具体取决于项目移动的次数。位置表中的最新日期将是项目的当前位置。
我正在基于此构建搜索。它可以工作,但查询需要很长时间才能完成。现在它需要大约35秒才能执行,但它似乎确实会返回所需的结果。
有没有办法只返回连接中的最新位置并使其运行得更快?
这是典型的查询
SELECT `inv_assets`.*, `inv_location`.`location_id`, `inv_location`.`responsible_user`
FROM (`inv_assets`)
LEFT JOIN `inv_location` ON inv_location.id = (SELECT inv_location.id FROM inv_location WHERE inv_location.asset_id = inv_assets.id ORDER BY id DESC LIMIT 1)
WHERE `location_id` LIKE '%207%'
我正在使用Codeigniter。这是我的搜索功能
function doadvsearch(){
$search_terms = array();
$post_data = $this->input->post(NULL, TRUE);
foreach ($post_data as $key => $value){
if ($value != ''){
$search_terms[$key] = $value;
}
}
$this->db->select('inv_assets.*, inv_location.location_id, inv_location._user');
$this->db->from('inv_assets');
$this->db->join('inv_location', 'inv_location.id = (SELECT inv_location.id FROM inv_location WHERE inv_location.asset_id = inv_assets.id ORDER BY id DESC LIMIT 1)', 'left', FALSE);
foreach ($search_terms as $skey => $svalue){
$this->db->or_like($skey, $svalue);
}
if (!empty($search_terms)){
$query = $this->db->get();
return $query->result_array();
}else{
return array();
}
}
答案 0 :(得分:0)
您应该在数据库中的表字段中添加始终使用的列的索引。或者您可以尝试$ this-> db->查询(STRAIGHT QUERY);而不是使用某些功能。
答案 1 :(得分:0)
这会创建一个递归查询,这是问题的根源。实际上,子查询在第一个查询的每一行执行一次。我不确定是否可以避免...
你可以使用GROUP BY
来获得更好的表现。例如:
SELECT *,
(SELECT MAX(date_moved) FROM inv_location AS l
WHERE l.asset_id = assets.id)
AS last_date_moved
FROM inv_assets AS assets
答案 2 :(得分:0)
找到解决方案并将其写入我的CI功能
function doadvsearch(){
$search_terms = array();
$location_fields = array('responsible_user', 'building_id', 'room_no', 'location_id');
$post_data = $this->input->post(NULL, TRUE);
foreach ($post_data as $key => $value){
if ($value != ''){
$search_terms[$key] = $value;
}
}
$this->db->select('inv_assets.*, lo.location_id, lo.responsible_user');
$this->db->from('inv_assets');
$this->db->join('inv_location lo', 'lo.asset_id = inv_assets.id', 'LEFT OUTER', FALSE);
$this->db->join('inv_location lo2', 'lo2.asset_id = inv_assets.id AND lo.id < lo2.id', 'LEFT OUTER', FALSE);
$this->db->where('lo2.id IS NULL', NULL, FALSE);
foreach ($search_terms as $skey => $svalue){
if (in_array($skey, $location_fields)){
$skey = "lo.$skey";
}
$this->db->or_like($skey, $svalue);
}
if (!empty($search_terms)){
$query = $this->db->get();
return $query->result_array();
}else{
return array();
}
}