CodeIgniter Active Record use "USING" in query - php

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();

Related

Left join 2 times raw query laravel doesn't work (Laravel)

I tried my raw query sql in laravel and i need to left join it 2 times but the print out is wrong. It different from mysql. I've tried in mysql and it works well
this is my code :
$tabel = DB::SELECT(DB::RAW("
SELECT codeh.info_code kh_infocode, codep.no_code khp_nocode,
codep.info_code khp_infocode,
codep.name_code khp_namecode, t.* FROM transactions t
LEFT JOIN users u ON t.user_id=u.id
LEFT JOIN divisions d ON d.id=u.division_id
LEFT JOIN all_codes codep ON t.code_p_id=codep.id
LEFT JOIN all_codes codeh ON t.allcode_id=codeh.id
WHERE 1=1
AND d.id=$div_id
AND codep.no_code LIKE '$allcode->no_code%'
$db_date
ORDER BY t.date, khp_nocode
"));
it works really well in sql but when i put it in laravel kh_infocode change and the value same like khp_infocode even though kh_infocode has different value with khp_infocode
Everything is in the official docs. It's not even long, go give it a read.
DB::table('transactions as t')
->select(
'codeh.info_code',
'kh_infocode',
'codep.no_code',
'khp_nocode',
'codep.info_code',
'khp_infocode',
'codep.name_code',
'khp_namecode',
't.*',
)
->leftJoin('users as u', 't.user_id', '=', 'u.id')
->leftJoin('all_codes as codep', 't.code_p_id', '=', 'codep.id')
->leftJoin('all_codes as codeh', 't.allcode_id', '=', 'codeh.id')
->where('d.id', '=', $div_id)
->where('codep.no_code', 'like', $allcode->no_code.'%')
->orderBy('t.date')
->orderBy('khp_nocode')
->get();
simply set SQL string directly without DB::RAW()
$tabel = DB::SELECT('your select statment');

PHP CodeIgniter multiple LEFT OUTER join in on query

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

Database Query Execution Takes Too Long

Am currently having this issue where my database query takes too long to execute and sometimes ends up failing with an error: Maximum Execution Time Exceeded... Am trying to select data from different tables that aren't directly related to each other, i.e One table is related to a table which is related to another table and so on, Some of this tables have over a thousand records, I have a feeling the structure of the different tables contributes to this headache, but I haven't been able to figure out how to reduce this execution time. Am using a CodeIgniter model where i created a function with the following sql query:
/**
* Get payment history based on search term
* #param string $search
* #param int $limt => default is 10
* #return mixed
**/
public function get_search_history($usertin, $search, $limit, $offset){
$this->db->select("
rv.name AS 'Revenue Name',rv.code AS 'Rev. Code',
m.name AS 'MDA',m.sector AS 'Sector', b.code AS 'Bank Code',
b.name AS 'Bank',p.amount AS 'Amount',p.channel AS 'Payment Channel',
p.date AS 'Payment Date',p.platform AS 'Platform',p.ref AS 'Reference',
t.tin AS 'TIN',t.active AS 'Is Active?',r.ref AS 'Receipt Reference'
");
$this->db->from('revenue AS rv');
$this->db->join('mda AS m', 'm.id = rv.mda_id', 'inner');
$this->db->join('payment AS p', 'p.revenue_id = rv.id', 'inner');
$this->db->join('bank AS b', 'b.id = p.bank_id', 'inner');
$this->db->join('tin AS t', 't.id = p.tin_id', 'inner');
$this->db->join('receipt AS r', 'r.id = p.receipt', 'inner');
$this->db->where('t.tin', $usertin);
$this->db->like('rv.code', $search);
$this->db->or_like('rv.name', $search);
$this->db->or_like('m.name', $search);
$this->db->group_by('t.id');
$this->db->order_by('p.date', 'ASC');
$this->db->limit($limit, $offset);
$query = $this->db->get();
return ( ( $query->num_rows() > 0 ) ? $query->result_array() : 0 );
}
The query is supposed to retrieve a user's payment history based on a particular search term or keyword!
It's easier to see from the above query what I meant when I said "...One table is related to a table which is related to another table..." I Just can't figure out a better way of doing this. Can anyone help me out? It's given me serious headaches the past couple of days!
This is the output of the query:
SELECT rv.name AS 'Revenue Name', rv.code AS 'Rev. Code', m.name AS
'MDA', m.sector AS 'Sector', b.code AS 'Bank Code', b.name AS 'Bank',
p.amount AS 'Amount', p.channel AS 'Payment Channel', p.date AS 'Payment
Date', p.platform AS 'Platform', p.ref AS 'Reference', t.tin AS 'TIN',
t.active AS 'Is Active?', r.ref AS 'Receipt Reference'
FROM `revenue` AS `rv`
INNER JOIN `mda` AS `m` ON `m`.`id` = `rv`.`mda_id`
INNER JOIN `payment` AS `p` ON `p`.`revenue_id` = `rv`.`id`
INNER JOIN `bank` AS `b` ON `b`.`id` = `p`.`bank_id`
INNER JOIN `tin` AS `t` ON `t`.`id` = `p`.`tin_id`
INNER JOIN `receipt` AS `r` ON `r`.`id` = `p`.`receipt`
WHERE `t`.`tin` = '1904260529-0001'
AND `rv`.`code` LIKE '%With%' ESCAPE '!'
OR `rv`.`name` LIKE '%With%' ESCAPE '!'
OR `m`.`name` LIKE '%With%' ESCAPE '!'
GROUP BY `t`.`id`
ORDER BY `p`.`date` ASC
LIMIT 3, 20
If you have this much tables to join frequently, there are 2 possible ways I can suggest.
1. Use CodeIgniter's feature Query Caching
You just have to enable it from database.php and have to give it a folder path where all cached queries will lie.
Then you can create hook or something to delete and regenerate that cached queries on particular condition.
2. Create View in MySQL
You can create View in MySQL which will be much faster. It can be done easily right from PHPMyAdmin even.
Hope this helps.
p.s. Try indexing proper columns.
Simple thumb rule is As more conditions in WHERE clause, As lower query will be

Laravel 5: Native SQL to Query Builder

I am trying to join 2 tables on Laravel 5 and have to use Query Builder. I have already got the sql for it but i am not able to convert it to Query Builder syntax. SQL is below
SELECT v.id, r.full_name, b.full_name, s.full_name
FROM vehicles v
LEFT JOIN clients r ON v.representive_client_id = r.id
LEFT JOIN clients b ON v.buyer_client_id = b.id
LEFT JOIN clients s ON v.seller_client_id = s.id
and what i tried is
$query_result = DB::table('vehicles')
->selectRaw($query)
->leftJoin('clients', 'vehicles.representive_client_id', '=', 'clients.id')
->leftJoin('clients', 'vehicles.buyer_client_id ', '=', 'clients.id')
->leftJoin('clients', 'vehicles.seller_client_id ', '=', 'clients.id')
->paginate(30);
The problem is i dont know how to use AS caluse for Query Builder as i need to retrive 3 different types of full_name columns from vehicles table.Anybody can help me about how to write it in a proper Query Builder syntax ?. Any help would be appreciated.
You can use aliases with select columns and tables as well as joins, because the Query Builder will know to quote them correctly. So you can do this without any problems:
$query_result = DB::table('vehicles v')
->select('v.id', 'r.full_name as r_name', 'b.full_name as b_name', 's.full_name as s_name')
->leftJoin('clients r', 'vehicles.representive_client_id', '=', 'r.id')
->leftJoin('clients b', 'vehicles.buyer_client_id ', '=', 'b.id')
->leftJoin('clients s', 'vehicles.seller_client_id ', '=', 's.id')
->paginate(30);
Of course, you can use whatever aliases you want for the selected columns. Actually one of the examples in the Query Builder Selects Documentation uses aliases: email as user_email.
To check the SQL query generated by the Query Builder you can use the toSql method. So in your case instead of ->paginate(30) you can have ->toSql(), which will return a string with the SQL generated by the Query Builder, which you can compare to your raw query and see if it matches.

CodeIgniter mySQL 2 table LEFT OUTER JOIN

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');

Categories