Laravel Eloquent left join query - mysql

I have like this query which work in plain sql:
SELECT users.id, users.name, roles.name
FROM users
LEFT JOIN model_has_roles ON model_has_roles.model_id = users.id
LEFT JOIN roles ON roles.id = model_has_roles.role_id
ORDER BY roles.name ASC
Using laravel I tried like this but it's doesn't work:
$user = $request->user();
$role = (array) $request->get('role', []);
$order = (array) $request->get('order');
$perPage = $request->get('perPage') ?? 10;
$users = User::where('id', '!=', $user->id);
if(count($role)) {
if (($key = array_search('admin', $role)) !== false) {
unset($role[$key]);
}
$users = $users->whereHas('roles', function ($query) use($role) {
return $query->whereIn('name', $role);
});
} else {
$users = $users->whereHas('roles', function ($query) {
return $query->whereIn('name', ['farmer', 'specialist', 'company']);
});
}
if(count($order) && isset($order['field'])) {
$orderType = $order['type'] ?? 'ASC';
if($order['field'] == 'role') {
$users = $users->leftJoin('model_has_roles', 'model_has_roles.model_id', '=', 'users.id')
->leftJoin('roles', 'roles.id', '=', 'model_has_roles.role_id')
->orderBy('roles.name', $orderType);
} else {
$users = $users->orderBy($order['field'], $orderType);
}
}
$users = $users->paginate($perPage);
Error message:
`"message": "SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous (SQL: select count(*) as aggregate from `users` left join `model_has_roles` on` `model_has_roles`.`model_id` = `users`.`id` left join `roles` on `roles`.`id` = `model_has_roles`.`role_id` where `id` != 3 and exists (select * from `roles` inner join `model_has_roles` on `roles`.`id` = `model_has_roles`.`role_id` where `users`.`id` = `model_has_roles`.`model_id` and `model_has_roles`.`model_type` = App\\Models\\User and `name` in (specialist, company)))",

Because your both models have id and after sql execute the query id column will be ambiguous so this will help you:
$users = User::where('id', '!=', $user->id);
change to
$users = User::where('users.id', '!=', $user->id);
Then try:
$users = $users->select(['users.id', 'users.name', 'roles.name'])
->leftJoin('model_has_roles', 'model_has_roles.model_id', '=', 'users.id')
->leftJoin('roles', 'roles.id', '=', 'model_has_roles.role_id')
->orderBy('roles.name', 'ASC');

Related

How To Select And Join two table with last record in codeigniter

i want join last row is_read column in ticket_message table to tickets table.
i used this sample code and the results are not sorted by id.
SELECT t.*,m.is_read
FROM tickets AS t
LEFT JOIN ticket_message AS m ON t.id = m.ticket_id
LEFT JOIN ticket_message AS m1 ON m.ticket_id = m1.ticket_id
AND m.id < m1.id
WHERE m1.id IS NULL
$this->db->select('t.*,m.is_read');
$this->db->from('tickets as t');
$this->db->join('ticket_message as m', 't.id = m.ticket_id', 'left');
$this->db->join('ticket_message as m1', 'm.ticket_id = m1.ticket_id AND m.id < m1.id', 'left');
$this->db->where('m1.id IS NULL', null, false);
$query = $this->db->get();
return $query;
what do i do.
Sorted by ID? I assume you mean ordered by ID.. in which case you just add this to your build query:
$this->db->order_by('t.id', 'ASC');
Your whole query:
$this->db->select('t.*,m.is_read');
$this->db->from('tickets as t');
$this->db->join('ticket_message as m', 't.id = m.ticket_id', 'left');
$this->db->join('ticket_message as m1', 'm.ticket_id = m1.ticket_id AND m.id < m1.id', 'left');
$this->db->where('m1.id IS NULL', null, false);
$this->db->order_by('t.id', 'ASC');
$query = $this->db->get();
return $query;

How can I add condition in db raw laravel?

My query db raw laravel like this :
public function getTopProduct($price = null) {
$products = DB::select(DB::raw('SELECT *
FROM (
SELECT a.*, b.name AS store_name, b.address
FROM products a
JOIN stores b ON b.id = a.store_id
WHERE a.status = 1
) AS product
GROUP BY store_id')
);
return $products;
}
I want to add condition
If price is not null, it will add condition price on the where
For example, price = 1000, then the query on the where like this :
WHERE a.status = 1 AND a.price < 1000
If price = null, the condition AND a.price < 1000 not executed
How can I do it?
Update
I slightly change my code flow
I try like this :
public function getTopProduct($price)
{
if($price == 1)
$price_condition = 'WHERE price > 1000';
else if($price == 2)
$price_condition = 'WHERE price >= 500 AND a.price <= 1000';
else if($price == 3)
$price_condition = 'WHERE price < 500';
else
$price_condition = '';
$products = DB::select('SELECT *
FROM (
SELECT a.*, b.name AS store_name, b.address
FROM products a
JOIN stores b ON b.id = a.store_id
WHERE a.status = 1
) AS product
GROUP BY store_id
'.$price_condition
);
return $products;
}
And it works
How do you think?
Whether my solution is correct? Or you have a better solution?
public function getTopProduct($price = null) {
if($price==null){
$products = DB::select(DB::raw('SELECT *
FROM (
SELECT a.*, b.name AS store_name, b.address
FROM products a
JOIN stores b ON b.id = a.store_id
WHERE a.status = 1
) AS product
GROUP BY store_id')
);
}else{
$products = DB::select(DB::raw('SELECT *
FROM (
SELECT a.*, b.name AS store_name, b.address
FROM products a
JOIN stores b ON b.id = a.store_id
WHERE a.status = 1 AND a.price='.$price.'
) AS product
GROUP BY store_id')
);
}
return $products;
}
You may use Advanced Join Clauses in Query Builder
DB::table('products')
->join('stores', function ($join) use ($price) {
$query = $join->on('stores.id', '=', 'products.store_id')
->where('products.status', '=', 1);
if (!empty($price)) {
$query->where('products.price', '<', 1000);
}
})
->select('products.*', 'stores.name AS store_name', 'stores.address')
->groupBy('products.store_id')
->get();
Try something like below code with your where condition:
$price = array_column($request->get('price'), 'id');
OR
$price = $request->get('price');
$query = DB::select(DB::raw('SELECT *
FROM (
SELECT a.*, b.name AS store_name, b.address
FROM products a
JOIN stores b ON b.id = a.store_id
WHERE a.status = 1
) AS product
GROUP BY store_id'))
->when($price == 1, function($query) use ($price) {
$query->where('price', '>', '1000');
})
->when($price == 2, function($query) use ($price) {
$query->where('price', '>=', '500')
->where('a.price', '<=', '1000');
})
->when($price == 3, function($query) use ($price) {
$query->where('price', '<', '500');
})
->when($price == '', function($query) use ($price) {
$query->where('your_where_when_price_empty');
})
->get();
Hope this helps you!

Converting SQL query to Laravel?

I have a very large query and many more that are even bigger.
I've tried to convert it to work with Laravel's DB class except it's not returning anything.
Is there something that can do this automatically? Like a converter?
What am I doing wrong here?
SELECT
cases.id
FROM cases
LEFT JOIN cases_cstm ON cases.id = cases_cstm.id_c
JOIN cases_contacts_1_c ON cases.id = cases_contacts_1_c.cases_contacts_1cases_ida AND cases_contacts_1_c.deleted = 0
JOIN contacts ON cases_contacts_1_c.cases_contacts_1contacts_idb = contacts.id AND contacts.deleted = 0
LEFT JOIN contacts_pal_policy_adviser_list_1_c ON contacts.id = contacts_pal_policy_adviser_list_1_c.contacts_pal_policy_adviser_list_1contacts_ida
LEFT JOIN pal_policy_adviser_list ON contacts_pal_policy_adviser_list_1_c.contacts_pal_policy_adviser_list_1pal_policy_adviser_list_idb = pal_policy_adviser_list.id
LEFT JOIN huge__insurance_carriers_cases_1_c ON cases.id = huge__insurance_carriers_cases_1_c.huge__insurance_carriers_cases_1cases_idb AND huge__insurance_carriers_cases_1_c.deleted = 0
LEFT JOIN huge__insurance_carriers ON huge__insurance_carriers_cases_1_c.huge__insurance_carriers_cases_1huge__insurance_carriers_ida = huge__insurance_carriers.id AND huge__insurance_carriers.deleted = 0
LEFT JOIN products_cases_1_c ON cases.id = products_cases_1_c.products_cases_1cases_idb
LEFT JOIN products ON products_cases_1_c.products_cases_1products_ida = products.id
WHERE cases.deleted = 0
AND contacts.id = 'b8a00721-40f1-7801-b4b9-50ce152ce2ec'
AND ((cases.status = 'Entered') or (cases.status = 'Submitted') or (cases.status = 'Approved') or (cases.status = 'Issued') or (cases.status = 'Gathering_Medical_Information') or (cases.status = 'Awaiting_Carrier_Offers') or (cases.status = 'All_Offers_In') or (cases.status = 'Informal_Entered') or (cases.status = 'Await_Del_Req')) GROUP BY cases.id ORDER BY cases_cstm.insured_name_c ASC LIMIT 0, 20
Laravel query
DB::table('cases')
->leftJoin('cases_cstm', 'cases.id', '=', 'cases_cstm.id_c')
->join('cases_contacts_1_c', 'cases.id', '=', 'cases_contacts_1_c.cases_contacts_1cases_ida')
->join('contacts', 'cases_contacts_1_c.cases_contacts_1contacts_idb', '=', 'contacts.id')
->leftJoin('contacts_pal_policy_adviser_list_1_c', 'contacts.id', '=', 'contacts_pal_policy_adviser_list_1_c.contacts_pal_policy_adviser_list_1contacts_ida')
->leftJoin('pal_policy_adviser_list', 'contacts_pal_policy_adviser_list_1_c.contacts_pal_policy_adviser_list_1pal_policy_adviser_list_idb', '=', 'pal_policy_adviser_list.id')
->leftJoin('huge__insurance_carriers_cases_1_c', 'cases.id', '=', 'huge__insurance_carriers_cases_1_c.huge__insurance_carriers_cases_1cases_idb')
->leftJoin('huge__insurance_carriers', 'huge__insurance_carriers_cases_1_c.huge__insurance_carriers_cases_1huge__insurance_carriers_ida', '=', 'huge__insurance_carriers.id')
->leftJoin('products_cases_1_c', 'cases.id', '=', 'products_cases_1_c.products_cases_1cases_idb')
->leftJoin('products', 'products_cases_1_c.products_cases_1products_ida', '=', 'products.id')
->where('contacts.id', '=', 'b8a00721-40f1-7801-b4b9-50ce152ce2ec')
->orWhere('cases.status', '=', 'Entered')
->orWhere('cases.status', '=', 'Submitted')
->orWhere('cases.status', '=', 'Approved')
->orWhere('cases.status', '=', 'Issued')
->orWhere('cases.status', '=', 'Gathering_Medical_Information')
->orWhere('cases.status', '=', 'Awaiting_Carrier_Offers')
->orWhere('cases.status', '=', 'All_Offers_In')
->orWhere('cases.status', '=', 'Informal_Entered')
->orWhere('cases.status', '=', 'Await_Del_Req');
->get();
$statuses = [...]; // array of statuses to compare
DB::table('cases')
// all your joins
->where('contacts.id', '=', 'b8a00721-40f1-7801-b4b9-50ce152ce2ec')
->whereIn(cases.status', $statuses)
->get(['cases.id']);
or (really, don't, just as an example):
DB::table('cases')
// all your joins
->where('contacts.id', '=', 'b8a00721-40f1-7801-b4b9-50ce152ce2ec')
->where(function($q) { // this will wrap all those OR WHERE clauses in AND ( .. )
$q->where(...)
// all the orWheres
->orWhere(...);
})
->get(['cases.id']);
Also, use DB::getQueryLog() after that to get the array of the queries, that were run by Laravel.

Assistance required converting MySQL function to PDO

I'm currently converting MySQL to PDO, I'm unsure if I wrote this function correctly,I'm also unsure of how to use sqlfiddle, so I resort to Stackoverflow.
If correct, anything to better the current code?
MySQL example :
PUBLIC FUNCTION Insert_Update($_iD, $update, $uploads){
$update = mysql_real_escape_string($update);
$time = time();
$_iP = $_SERVER['REMOTE_ADDR'];
$query = mysql_query("SELECT post_iD,message FROM `Posts` WHERE uid_fk='$_iD' ORDER by post_iD DESC LIMIT 1") or die(mysql_error());
$result = mysql_fetch_array($query);
if ($update!=$result['message']) {
$uploads_array = explode(',',$uploads);
$uploads = implode(',',array_unique($uploads_array));
$query = mysql_query("INSERT INTO `Posts` (message, uid_fk, _iP,created,uploads) VALUES (N'$update', '$_iD', '$_iP','$time','$uploads')") or die(mysql_error());
$newquery = mysql_query("SELECT M.post_iD, M.uid_fk, M.message, M.created, U._iUsername FROM Posts M, users U where M.uid_fk=U._iD and M.uid_fk='$_iD' order by M.post_iD desc limit 1 ");
$result = mysql_fetch_array($newquery);
return $result;
} else {
return false;
}
}
PDO Example:
PUBLIC FUNCTION Insert_Update($_iD, $update, $uploads){
$sth = $this->db->prepare("SELECT post_iD,message FROM `Posts` WHERE uid_fk = :id ORDER by post_iD DESC LIMIT 1")
$sth->execute(array('id' => $_iD));
$result = $sth->FetchAll(PDO::FETCH_ASSOC);
if ( $update!=$result['message'] ){
$uploads_array = explode(',',$uploads);
$uploads = implode(',',array_unique($uploads_array));
$sth = $this->db->prepare("INSERT INTO Posts (message, uid_fk, _iP,created,uploads) VALUES ( :update, :id, :ip, :time, :uploads)")
$sth->bindValue(':update', $update);
$sth->bindValue(':id', $_iD);
$sth->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
$sth->bindValue(':time', time());
$sth->bindValue(':uploads', $uploads);
$sth->execute()
$sth = $this->db->prepare("
SELECT M.post_iD, M.uid_fk, M.message, M.created, U._iUsername
FROM Posts M, users U
WHERE M.uid_fk=U._iD
AND M.uid_fk = :id
ORDER by M.post_iD DESC LIMIT 1 ");
$sth->execute(array(':id' => $_iD));
$result = $sth->FetchAll(PDO::FETCH_ASSOC);
return $result;
} else {
return false;
}
}

Zend DB Union not working

I was given the task of translating an old query into Zend and all was going well until I went to create the union. I cannot post the actual contents of the query due to company regulations but basically what I have is:
$sql1 = $db->select()
->from(array('t' => 'tableOne'), array('t.id'))
->joinLeft(array('tt' => 'tableTwo'), 'tt.fk_tableOne_id = t.id', array())
->where($db->quoteInto('tt.active = ?', 'Y'));
$sql2 = $db->select()
->from(array('t' => 'tableOne'), array('t.id'))
->joinLeft(array('tt' => 'tableTwo'), 'tt.fk_tableOne_id = t.id', array())
->where($db->quoteInto('tt.active = ?', 'Y'));
$select = $db->select()->union(array($sql1, $sql2))->order('t.id');
Now, if I do a fetchAll on $sql1, it works. If I do a fetchAll on $sql2, it works. However, when I do a fetchAll on $select I get an error 1064 Syntax Error.
The sql string echoed by echo $select is basically
(ORDER BY `t.id` ASC) UNION (SELECT ... ) UNION (SELECT ...)
With the syntax error near ORDER BY ...
It seems like this should all be working since the two queries work independently, any ideas?
I tried a slightly modified query from yours:
$sql1 = $zdb->select()
->from(array('t' => 'articles'), array('t.id'))
->joinLeft(array('tt' => 'users'), 'tt.id = t.author_id', array())
->where($zdb->quoteInto('tt.level = ?', 'editor'));
$sql2 = $zdb->select()
->from(array('t' => 'blogs'), array('t.id'))
->joinLeft(array('tt' => 'users'), 'tt.id = t.updated_by', array())
->where($zdb->quoteInto('tt.level = ?', 'editor'));
$select = $zdb->select()->union(array($sql1, $sql2))->order('id');
echo $select;
and got the following:
SELECT `t`.`id` FROM `articles` AS `t` LEFT JOIN `users` AS `tt` ON tt.id = t.author_id
WHERE (tt.level = 'editor') UNION SELECT `t`.`id` FROM `blogs` AS `t` LEFT JOIN `users`
AS `tt` ON tt.id = t.updated_by WHERE (tt.level = 'editor') ORDER BY `id` ASC
What version of the framework do you have?