我正在研究search
功能。
我创建了一个搜索表单,用户可以根据Type
,ope
& Formate
。
我在加入查询中使用了子查询来获得所需的结果。
我在MySQL Workbench
测试了我的查询,但它工作正常。
但是当我使用查询构建器技术在Codeigniter中尝试相同的查询时,我遇到了一个问题。
以下是在工作台中正常工作的查询:
SELECT (*)
FROM `App`
LEFT JOIN `App_type`
ON `App_type`.`app_id` = `App`.`id`
LEFT JOIN `App_formate`
ON `App_formate`.`app_id` = `App`.`id`
WHERE `App`.`id` IN(select app_id FROM App_type WHERE type_id in (3,2,6) group by app_id HAVING COUNT(*) = 3)
AND `App_formate`.`formate_id` IN('1', '3')
AND `jobs`.`ope_min` <= '3'
AND `jobs`.`ope_max` >= '3'
GROUP BY `jobs`.`id`;
这是我使用的连接查询:
$subquery = "select app_id FROM App_type WHERE type_id in ($selected_type) group by app_id HAVING COUNT(*) = $type_count";
$search_app_query = $this->db
->select('*')
->from('App')
->join('App_type', 'App_type.app_id = App.id', 'left outer')
->join('App_formate', 'App_formate.app_id = App.id', 'left outer')
->where_in('App.id',$subquery) //<-- Here is the problem
->where_in('App_formate.formate_id',$data['selected_formates'])
->where('App.ope_min <=',$data['ope_value'])
->where('App.ope_max >=',$data['ope_value'])
->group_by("App.id", "desc")
->get();
我正在调试此问题时显示
I have found the problem is in this part of the query:
"WHERE `App`.`id` IN('select app_id
FROM App_type
WHERE type_id in (3,2,6)
group by app_id HAVING COUNT(*) = 3')"
此子查询中的单引号正在产生问题。
到目前为止我尝试过:
要删除此单引号,我已尝试
REPLACE($subquery, '''', '')
->where_in('App.id',trim($subquery,"'"))
$subquery_improved = substr($subquery, 1, -1);
但所有这些解决方案都无效。他们没有删除单引号。
注意:我知道$this->db->query()
但不想使用它。
答案 0 :(得分:8)
你的任务看起来很简单
而不是
->where_in('App.id',$subquery) //<-- Here is the problem
您可以尝试以下
->where("App.id IN (".$subquery.")",NULL, false)
您可以在Codeigniter文档here中找到这些确切的信息(第4点和下面的部分)。
答案 1 :(得分:6)
我的方法将在下面以更通用的方式进行。我总是试图遵循MVC模式,同时打破小功能的功能。虽然您没有共享所有代码,但无论如何我都会建议。
您应该将我的自定义名称更改为函数,数组等,以便它与您的代码匹配。希望它有所帮助。
模型功能
public function getApp_ids($selected_type, $type_count) {
$subquery = "select app_id FROM App_type WHERE type_id in ($selected_type) group by app_id HAVING COUNT(*) = $type_count";
$result = $subquery->get();
if($result->num_rows() > 0) //the check here is relevant to your data
return $result->result_array();
return false;
}
模型功能
public function searchApp($appIds, $data) {
//$appIds and $data are parameters to this function.
$search_app_query = $this->db
->select('*')
->from('App')
->join('App_type', 'App_type.app_id = App.id', 'left outer')
->join('App_formate', 'App_formate.app_id = App.id', 'left outer')
->where_in('App.id',$appIds) //pass the array of your IDs
->where_in('App_formate.formate_id',$data['selected_formates'])
->where('App.ope_min <=',$data['ope_value'])
->where('App.ope_max >=',$data['ope_value'])
->group_by("App.id", "desc")
->get();
if($search_app_query->num_rows() > 0) //again, the check is yours
return $search_app_query->result_array();
return false;
}
在您的控制器中,类似这样
public function YOUR_FUNCTION($selected_type, $type_count) {
//call this function from model to grab the app_id you want. Don't forget to pass the parameters you sql needs.
$appIdsResult = $this->YOUR_MODEL->getApp_ids($selected_type, $type_count);
//Manipulate your result in another array, so you can get rid off the indexes and do some checks if you want
$appIds = array();
foreach ($appIdsResult as $appId) {
array_push($appIds, $appId['app_id']); //Check the index app_id, it is the result from your DB.
}
//Call searchApp from your model and pass the found $appIds and your $data ofcourse
$result = $this->YOUR_MODEL->searchApp($appIds, $data);
//In $result will be your answer
}
答案 2 :(得分:4)
替换此代码:
->where_in('App.id',$subquery) //<-- Here is the problem
使用此代码:
->where_in("App.id", $subquery, FALSE)
第3个参数accept Boolean,用于确定函数是否应该转义值和标识符。设置为FALSE时,它不使用单引号作为转义字符。
希望这有帮助。
答案 3 :(得分:3)
使用手册查询(不安全,非常非常使用)
$sql = "SELECT ....[Your Query].....":
$query = $this->db->query($sql);
if ($query->num_rows() > 0){
// Found
}else{
// Not Found
}
答案 4 :(得分:3)
//首先确认子查询只返回一个结果,如果不在子查询中更改
$subquery = "select GROUP_CONCAT(CONCAT(\"'\",app_id,\"'\")) FROM App_type WHERE type_id in ($selected_type) group by app_id HAVING COUNT(*) = $type_count";
$search_app_query = $this->db
->select('*')
->from('App')
->join('App_type', 'App_type.app_id = App.id', 'left outer')
->join('App_formate', 'App_formate.app_id = App.id', 'left outer')
->where_in('App.id',$subquery,false) //<-- pass 3rd parameter as false for removing single quotes
->where_in('App_formate.formate_id',$data['selected_formates'])
->where('App.ope_min <=',$data['ope_value'])
->where('App.ope_max >=',$data['ope_value'])
->group_by("App.id", "desc")
->get();
答案 5 :(得分:1)
我认为您的$subquery
被视为参数字符串,而不是查询
活动记录方法的一般语法是
->where_in('field_name', array() || 'string values');
你$subquery
必须像这样
$subquery = $this->db
->select('app_id')
->from('App_type')
->where_in('type_id',array(3,2,6))
->group_by('app_id')
->having(' COUNT(*) = 3')
->get()
->row()
->app_id;
希望它能奏效:)
答案 6 :(得分:1)
而不是
SELECT (*)
使用
SELECT *
而不是
WHERE `App`.`id` IN(
select app_id FROM App_type
WHERE type_id in (3,2,6) group by app_id HAVING COUNT(*) = 3)
使用
JOIN (
select app_id FROM App_type
WHERE type_id in (3,2,6) group by app_id HAVING COUNT(*) = 3
) AS x ON x.app_id = App.id
(翻译成CodeIgniter留给读者练习。)
答案 7 :(得分:1)
首先在查询之后,输入以下代码:
echo $ this-&gt; db-&gt; last_query(); exit;
这将打印查询,您将知道问题在哪里。同时复制该查询并尝试在phpmyadmin中运行它。
也可以尝试这种类型的解决方案,因为您有单引号问题:
在子查询中使用单引号写入$ type_count,即'$ type_count'
->where("App.ope_min <='",$data['ope_value']."'")
->where("App.ope_max >='",$data['ope_value']."'")
->group_by("App.id", "desc")
->get();
如果您想问别的话,请告诉我。
答案 8 :(得分:1)
只需在where_in语句中添加第3个参数即可。试试这个 -
$subquery = "select app_id FROM app_type WHERE type_id in (3,2,6) group by app_id HAVING COUNT(*) = 3";
$search_app_query = $this->db
->select('*')
->from('app')
->join('app_type', 'app_type.app_id = app.id', 'left outer')
->join('app_formate', 'app_formate.app_id = app.id', 'left outer')
->where_in('app.id',$subquery, FALSE)
->where_in('app_formate.formate_id',array(1,3))
->where('app.ope_min <=',3)
->where('app.ope_max >=',3)
->group_by("app.id", "desc")
->get()->result();
答案 9 :(得分:1)
我建议你不要将子查询直接放在条件的位置,因为你有时也可能没有结果。所以最好的方法是像这样单独执行子查询。
$subdata = $this->db->select("app_id ")->from("App_type ")->where_in("type_id",$selected_type)->group_by(""app_id)->having("COUNT(*) = $type_count")->get()->result_array();
$search_app_query = $this->db
->select('*')
->from('App')
->join('App_type', 'App_type.app_id = App.id', 'left outer')
->join('App_formate', 'App_formate.app_id = App.id', 'left outer');
if(!empty($subdata)) {
$this->db->where_in('App.id',$subdata);
}
$this->db->where_in('App_formate.formate_id',$data['selected_formates'])
->where('App.ope_min <=',$data['ope_value'])
->where('App.ope_max >=',$data['ope_value'])
->group_by("App.id", "desc")
->get();
答案 10 :(得分:0)
感谢大家的建议。
我找到了解决问题的方法而不改变我的其他代码。
感谢sintakonte-SO user他的评论是解决此问题的关键。
解决方案只是我想要的一行代码的更改。
$search_app_query = $this->db
->select('*')
->from('App')
->join('App_type', 'App_type.app_id = App.id', 'left outer')
->join('App_formate', 'App_formate.app_id = App.id', 'left outer')
// This is what he suggested me to change and it works.
->where('App.id IN('.$subquery.')')
->where_in('App_formate.formate_id',$data['selected_formates'])
->where('App.ope_min <=',$data['ope_value'])
->where('App.ope_max >=',$data['ope_value'])
->group_by("App.id", "desc")
->get();
再次感谢sintakonte-SO user。