Я работаю над функцией search
. Я создал форму поиска, в которой пользователь может искать приложение на основе Type
, ope
& Formate
.
Я использовал подзапрос в моем запросе соединения, чтобы получить желаемый результат. Я тестировал свой запрос в MySQL Workbench
он работает нормально.
Но когда я пробовал тот же запрос в Codeigniter, используя технику построения запросов, я столкнулся с проблемой.
Вот запрос, который отлично работает в workbench:
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()
но не хочу этого использовать.
Ваша задача выглядит довольно просто
вместо
->where_in('App.id',$subquery) //<-- Here is the problem
вы можете попробовать следующее
->where("App.id IN (".$subquery.")",NULL, false)
Вы можете найти эту точную информацию в документации Codeigniter здесь (пункт 4 и раздел ниже).
Мой подход был бы чем-то вроде ниже, более общим образом. Я всегда стараюсь следовать шаблону 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 }
замените этот код:
->where_in('App.id',$subquery) //<-- Here is the problem
с этим кодом:
->where_in("App.id", $subquery, FALSE)
третий параметр принимает Boolean, чтобы определить, должна ли функция избегать значения и идентификатора или нет. Если установлено значение FALSE, он не использует одиночную кавычку как escape-символ.
Надеюсь это поможет.
РУКОВОДСТВО ПО ЭКСПЛУАТАЦИИ (небезопасно, используйте очень-очень)
$sql = "SELECT ....[Your Query].....": $query = $this->db->query($sql); if ($query->num_rows() > 0){ // Found }else{ // Not Found }
// сначала подтвердить, что подзапрос возвращает только один результат, если не изменить подзапрос
$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();
Я думаю, ваш $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;
Надеюсь, это сработает 🙂
Вместо
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 оставлен в качестве упражнения для читателя.)
Прежде всего после запроса, поставьте этот код:
echo $ this-> db-> 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();
Дайте мне знать, если вы хотите спросить что-то еще.
Просто добавьте третий параметр в оператор where_in. Попробуй это –
$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();
Я бы посоветовал вам не вводить sub-запрос непосредственно в состояние, в котором вы также можете иногда иметь нулевой результат. Таким образом, лучший способ – выполнить свой подзапрос отдельно, как это.
$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();
Спасибо всем вам за ваши предложения.
У меня есть способ решить мою проблему, не изменяя мой другой код.
Благодаря пользователю sintakonte-SO его комментарий был ключом к решению этой проблемы.
Решение – это просто изменение одного кода строки, который я раньше хотел.
$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 снова.