I'm using PHP CodeIgniter to query from my Database. I need to use multiple LEFT OUTER joins. The join uses multiple conditions (I'm not sure it is supported as of the bug). My query results have the same value for both parameters I want to fetch:
Query:
$this->db->select('anonymous.*,
count(items_likes.id) as all_likes, count(items_comments.id) as all_comments');
$this->db->from('anonymous');
$this->db->where('anonymous.fid', $feed_id);
$this->db->group_by('anonymous.id');
$this->db->join('all_users', 'all_users.id = anonymous.uid', 'left outer');
$this->db->join('images', 'images.ud = anonymous.uid AND images.fid = anonymous.fid', 'left outer');
$this->db->join('items_likes', 'items_likes.uid = anonymous.uid AND items_likes.fid = anonymous.fid', 'left outer');
$this->db->join('items_comments', 'items_comments.uid = anonymous.uid AND items_comments.fid = anonymous.fid', 'left outer');
$list = $this->db->get()->result();
anonymous: is a table with unregistered users
fid: Is the feed id
images: Is a table of all the images that were uploaded to the feed
items_likes: Is all the users' likes per image
items_comments: Is all the users' comments per image
The problem is that all_comments always return the same value as all_likes.
I'm not sure if the multiple LEFT-OUTER joins are the problem or maybe the fact that I'm using multiple conditions in every join statement i.e.
items_comments.uid = anonymous.uid AND items_comments.fid = anonymous.fid
The log result:
"all_likes":"12","all_comments":"12"
although I have 12 likes, the comments should be 3
If I write the query as follows the result is ok:
$this->db->select('anonymous.*,
(SELECT count( items_likes.id ) FROM items_likes WHERE items_likes.uid = anonymous.uid AND items_likes.fid = anonymous.fid) as all_likes,
(SELECT count( items_comments.id ) FROM items_comments WHERE items_comments.uid = anonymous.uid AND items_comments.fid = anonymous.fid) as all_comments');
$this->db->from('anonymous');
$this->db->where('anonymous.fid', $feed_id);
$this->db->group_by('anonymous.id');
$this->db->join('all_users', 'all_users.id = anonymous.uid', 'left outer');
$this->db->join('images', 'images.ud = anonymous.uid AND images.fid = anonymous.fid', 'left outer');
//$this->db->join('items_likes', 'items_likes.uid = anonymous.uid AND items_likes.fid = anonymous.fid', 'left outer');
//$this->db->join('items_comments', 'items_comments.uid = anonymous.uid AND items_comments.fid = anonymous.fid', 'left outer');
$list = $this->db->get()->result();
Left outer join produces a complete set of records from Table A, with
the matching records (where available) in Table B. If there is no
match, the right side will contain null.
You need to add the records which contain NULL
add this where clause to your query:
$this->db->->where('items_comments.uid IS NULL')
more info on joins here
Related
I want to join multiple tables, as in my picture:
Here is my code:
$this->db->select('
pt2.turl as `p_img`,
p.title as `p_title`,
p.text as `p_text`,
p.create as `p_date`,
pt3.turl as `c_img`,
u.name as `c_name`,
c.text as `c_text`,
c.create as `c_date`
');
$this->db->from('posts as p, users as u, photos as pt2, photos as pt3');
$this->db->join('comments as c', 'p.id=c.pid AND u.id=c.uid');
$this->db->join('posts as p2', 'p2.pid=pt2.id', 'rihgt');
$this->db->join('users as u2', 'u2.photoid=pt3.id', 'right');
$this->db->order_by('c.id', 'DESC');
$this->db->limit('7');
$qry = $this->db->get();
return $qry->result();
If I understand you correctly, this is kind of what you're looking for. I haven't tried it out so it may not be exact, but you shouldn't need to make 2 table associations (pt2 and pt3) for the same table in the join. Just Include them in the select and join on the unique ID's
The "Left" is a join that is centered around you're left table so everything hangs off of that. Since you are joining the users table before the photo table, you should be able to join on its columns.
Hope this helps. Let me know if I missed something. :)
$select = array(
pt2.turl as `p_img`,
p.title as `p_title`,
p.text as `p_text`,
p.create as `p_date`,
pt2.turl as `c_img`,
u.name as `c_name`,
c.text as `c_text`,
c.create as `c_date`
);
//Set tables to variables. Just makes it easier for me
$postsTable = "posts as p"; //This will be your left table.
$userTable = "Users as u";
$commentsTable = "comments as c";
$photosTable = "photos as pt2";
$this
->db
->select($select)
->from($postsTable)
->join($userTable, "p.uid = u.id", "left")
->join($commentsTable, "p.cid = c.id", "left")
->join($photosTable, "u.photoid = pt2.id", "left")
->get();
I solved this problem myself
It would be like this:
$select= array (
//'*',
'pt.turl p_img',
'p.title p_title',
'p.text p_text',
'p.create p_date',
'pt2.turl c_img',
'c.text c_text',
'u.name c_name',
'c.create c_date'
);
$from = array (
'posts p'
);
$qry = $this
->db
->select($select)
->from($from)
->join('comments c', 'c.pid=p.id')
->join('photos pt', 'pt.id=p.pid')
->join('users u', 'u.id=c.uid')
->join('photos pt2', 'u.photoid=pt2.id')
->order_by('c.create', 'DESC')
->limit('7')
->get();
return $qry->result();
I am working on a search functionality.
I have created a search form in which user can search an Application based on Type,ope & Formate.
I have used a subquery in my join query to get the desired result.
I have tested my query in MySQL Workbench nad it's working fine.
But when I tried that same query in Codeigniter using query builder technique then I am facing a problem.
Here is the query which is worked fine in 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`;
This is the join query which I use:
$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();
While I am debugging this problem it shows the
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')"
that single quote in this subquery is creating a problem.
What I have tried so far:
To remove this single quote I have tried
REPLACE($subquery, '''', '')
->where_in('App.id',trim($subquery,"'"))
$subquery_improved = substr($subquery, 1, -1);
But all this solution is not working. They are not removing the single quote.
Note: I am aware of $this->db->query() but do not want to use that.
Your task looks pretty simple
instead of
->where_in('App.id',$subquery) //<-- Here is the problem
you can try the following
->where("App.id IN (".$subquery.")",NULL, false)
You can find this exact information in the Codeigniter Documentation here (point 4 and the section below).
My approach would be something like below, in a more generic way. I am always trying to follow the MVC pattern while breaking the functionality in small functions. Although you didn't share all of your code, i will suggest it anyway.
You should change my custom given names to functions, arrays etc. so it matches your code. Hope it helps.
Model function
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;
}
Model Function
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;
}
In your Controller, something like this
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
}
replace this code:
->where_in('App.id',$subquery) //<-- Here is the problem
with this code:
->where_in("App.id", $subquery, FALSE)
the 3rd parameter accept Boolean to determine if the function should escape the value and identifier or not. When set to FALSE, it does not use single quote as escape char.
Hope this helps.
USE MANUAL QUERY ( unsafe ,use very very becareful)
$sql = "SELECT ....[Your Query].....":
$query = $this->db->query($sql);
if ($query->num_rows() > 0){
// Found
}else{
// Not Found
}
//first confirm subquery return only one result if not change in subquery
$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();
I think your $subquery was considered as a parameter string, not as a query.
The general syntax of active record method is
->where_in('field_name', array() || 'string values');
You $subquery have to be like this
$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;
Hope it will work :)
Instead of
SELECT (*)
use
SELECT *
Instead of
WHERE `App`.`id` IN(
select app_id FROM App_type
WHERE type_id in (3,2,6) group by app_id HAVING COUNT(*) = 3)
use
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
(Translating into CodeIgniter is left as an exercise to the reader.)
First of all after the query, put this code:
echo $this->db->last_query();exit;
This will print the query, and you will have an idea where's the issue. Also copy that query and try to run it in phpmyadmin.
Also try this type of solution as you have single quote issues:
In subquery write $type_count using single quotes i.e '$type_count'
->where("App.ope_min <='",$data['ope_value']."'")
->where("App.ope_max >='",$data['ope_value']."'")
->group_by("App.id", "desc")
->get();
Let me know if you want to ask something else.
Just add a 3rd parameter in where_in statement. Try this -
$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();
I would suggest you not to put sub query directly in where in condition because you may also sometimes have zero result. So the best way is to execute your subquery separately like this.
$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();
Thanks To All of you for your suggestions.
I have Find the way to solve my problem without altering my other code.
Thanks to sintakonte-SO user his comment has been the key to solve this problem.
The Solution is just the change of one line code which earlier i want.
$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();
Many thanks to sintakonte-SO user again.
I am trying to replicate the following query using Active Record in CodeIgniter but I can't find where in the documentation or searching how you use USING in a query.
SELECT *
FROM categories C
LEFT OUTER JOIN motorcycle_brands MB
USING ( CatID )
LEFT OUTER JOIN powersport_categories PS
USING ( CatID )
WHERE C.CatID = :uniqueID
This is what I have now:
$this->db->select('*');
$this->db->from('categories C');
$this->db->join('motorcycle_brands MB', 'CatID', 'left outer');
$this->db->join('powersport_categories PS', 'CatID', 'left outer');
$this->db->where('C.CatID =', $this->option_id);
$suboptions = $this->db->get();
I have tried changing
$this->db->join('motorcycle_brands MB', 'USING (CatID)', 'left outer');
$this->db->join('powersport_categories PS', 'USING (CatID)', 'left outer');
There is no built-in support for JOIN using USING in the active record class. The best that you can do is change the join() function in "system/database/DB_active_rec.php" this file.
Please refer this question for the complete reference.
codeigniter active records join with using?
The USING clause is used if several columns share the same name but you don’t want to join using all of these common columns. The columns listed in the USING clause can’t have any qualifiers in the statement, including the WHERE clause:
The ON clause is used to join tables where the column names don’t match in both tables. The join conditions are removed from the filter conditions in the WHERE clause:
So your code should be,
$this->db->select('*');
$this->db->from('categories C');
$this->db->join('motorcycle_brands MB', 'MB.CatID = C.Id', 'left outer');
$this->db->join('powersport_categories PS', 'C.Id = PS.CatID ', 'left outer');
$this->db->where('C.CatID =', $this->option_id);
$suboptions = $this->db->get();
everyone.
I'm using CodeIgniter, and I'm not getting results for this query:
$this->load->database();
$this->db->select('*');
$this->db->from('users');
$this->db->join('show_guides', 'show_guides.user_id = users.user_id');
$this->db->where('users.user_id', $user_id['user_id'], 'left outer');
$query = $this->db->get();
foreach ($query->result_array() as $row) {
$results = $row;
}
The 'users' table will always have results, but sometimes the user won't have a row in the 'show_guides' table. When the 'show_guides' table doesn't have results, the query doesn't return results from the 'users' table.
$row doesn't exist when 'show_guides' produces no results. I only get results when both tables have data with the matching users.user_id .
Any suggestions?
Thanks!
EDIT
To avoid any confusion, this query gives me the results I need, but I want to use the CodeIgniter db objects.
SELECT u.*,s.*
FROM users u
LEFT OUTER JOIN show_guides s ON u.user_id = s.user_id
WHERE u.user_id = 155;
This gives results even if show_guides is empty.
You want to put your 'left outer' in the join() function, not the where()
$this->db->join('show_guides', 'show_guides.user_id = users.user_id', 'left outer');
Can someone Tell me how to join 3 table with php?
Example
SELECT FROM table1, table2,table on INNERJOIN -------------------
let I have 3 table.(question table ,answer table and category table)
Here is example form my webpage.
Time remaining 30 minutes(I will get "30 minutes" form Category table)
1. Question (from question table)
2. answer (from answer table)
I don't know how to join 3 table.
it should be like that,
$this->db->select('*');
$this->db->from('table1');
$this->db->join('table2', 'table1.id = table2.id');
$this->db->join('table3', 'table1.id = table3.id');
$query = $this->db->get();
as per CodeIgniters active record framework
I believe that using CodeIgniters active record framework that you would just use two join statements one after the other.
eg:
$this->db->select('*');
$this->db->from('table1');
$this->db->join('table1', 'table1.id = table2.id');
$this->db->join('table1', 'table1.id = table3.id');
$query = $this->db->get();
Give that a try and see how it goes.
I created a function to get an array with the values for the fields and to join. This goes in the model:
public function GetDataWhereExtenseJoin($table,$fields,$data) {
//pega os campos passados para o select
foreach($fields as $coll => $value){
$this->db->select($value);
}
//pega a tabela
$this->db->from($table);
//pega os campos do join
foreach($data as $coll => $value){
$this->db->join($coll, $value);
}
//obtem os valores
$query = $this->db->get();
//retorna o resultado
return $query->result();
}
This goes in the controller:
$data_field = array(
'NameProduct' => 'product.IdProduct',
'IdProduct' => 'product.NameProduct',
'NameCategory' => 'category.NameCategory',
'IdCategory' => 'category.IdCategory'
);
$data_join = array
( 'product' => 'product_category.IdProduct = product.IdProduct',
'category' => 'product_category.IdCategory = category.IdCategory',
'product' => 'product_category.IdProduct = product.IdProduct'
);
$product_category = $this->mmain->GetDataWhereExtenseJoin('product_category', $data_field, $data_join);
result:
echo '<pre>';
print_r($product_category);
die;
I think in CodeIgniter the best to use ActiveRecord as wrote above.
One more thing: you can use method chaining in AR:
$this->db->select('*')->from('table1')->join('table2','table1.id=table2.id')->...
$this->db->select('*');
$this->db->from('table1');
$this->db->join('table2', 'table1.id = table2.id','JOIN Type');
$this->db->join('table3', 'table1.id = table3.id');
$query = $this->db->get();
this will give you result from table1,table2,table3 and you can use any type of join in the third variable of $this->db->join() function such as inner,left, right etc.
For executing pure SQL statements (I Don't Know About the FRAMEWORK- CodeIGNITER!!!)
you can use SUB QUERY!
The Syntax Would be as follows
SELECT t1.id
FROM example t1 INNER JOIN
(select id from (example2 t1 join example3 t2 on t1.id = t2.id)) as t2 ON t1.id = t2.id;
Hope you Get My Point!
$this->db->select('*');
$this->db->from('table1');
$this->db->join('table2', 'table1.id = table2.id', 'inner');
$this->db->join('table3', 'table1.id = table3.id', 'inner');
$this->db->where("table1", $id );
$query = $this->db->get();
Where you can specify which id should be viewed or select in specific table. You can also select which join portion either left, right, outer, inner, left outer, and right outer on the third parameter of join method.
you can modiv your coding like this
$this->db->select('a.nik,b.nama,a.inv,c.cekin,c.cekout,a.tunai,a.nontunai,a.id');
$this->db->select('DATEDIFF (c.cekout, c.cekin) as lama');
$this->db->select('(DATEDIFF (c.cekout, c.cekin)*c.total) as tagihan');
$this->db->from('bayar as a');
$this->db->join('pelanggan as b', 'a.nik = b.nik');
$this->db->join('pesankamar_h as c', 'a.inv = c.id');
$this->db->where('a.user_id',$id);
$query = $this->db->get();
return $query->result();
i hope can be resolve your SQL
function fetch_comments($ticket_id){
$this->db->select('tbl_tickets_replies.comments,
tbl_users.username,tbl_roles.role_name');
$this->db->where('tbl_tickets_replies.ticket_id',$ticket_id);
$this->db->join('tbl_users','tbl_users.id = tbl_tickets_replies.user_id');
$this->db->join('tbl_roles','tbl_roles.role_id=tbl_tickets_replies.role_id');
return $this->db->get('tbl_tickets_replies');
}