Sql leftJoin query using laravel syntax showing error - mysql

This is my query that i used for left join, it is working fine but something is missing when I convert it to laravel syntax.
Query to convert is
$result = DB::select("select amenities.name as
name,amenities.type_id,amenities.id as id, amenities.icon, rooms.id as status
from amenities left join rooms on find_in_set(amenities.id, rooms.amenities)
and rooms.id = $room_id and type_id !=4");
and the I am doing this
$result = DB::table('amenities')
->select('amenities.name as name', 'amenities.type_id' , 'amenities.id as id'
, 'amenities.icon', 'rooms.id as status' )
->leftJoin('rooms', function ($join) {
$join->on('FIND_IN_SET(amenities.id, rooms.amenities)')
->where('rooms.id' , '=', '$room_id')
->where('type_id','!=', 4);
})->get();
The error is
InvalidArgumentException in
F:\xampp\htdocs\arheb\Arheb\vendor\laravel\framework\src\Illuminate\Database\Query\JoinClause.php
line 79: Not enough arguments for the on clause.

Your query is wrong. I assume that amenities.id and rooms.amenities are attributes of amenities and rooms table respectively.
MySQL FIND_IN_SET() returns the position of a string if it is present (as a substring) within a list of strings.
You need to pass column names in first and second parameter of on() function.
$result = DB::table('amenities')
->select('amenities.name as name', 'amenities.type_id' , 'amenities.id as id'
, 'amenities.icon', 'rooms.id as status' )
->leftJoin('rooms', function ($join) {
$join->on('amenities.id', '=', 'rooms.amenities')
->where('rooms.id' , '=', '$room_id')
->where('type_id','!=', 4);
})->get();

I think you can try this:
$result = DB::table('amenities')
->select('amenities.name as name', 'amenities.type_id' , 'amenities.id as id'
, 'amenities.icon', 'rooms.id as status' )
->leftJoin('rooms', function ($join) {
$join->on(DB::raw("find_in_set(amenities.id, rooms.amenities)"))
->where('rooms.id' , '=', '$room_id')
->where('type_id','!=', 4);
})->get();
Hope this work for you!

Related

how to run mysql query in Laravel

I want to transform my MySql query into a Query in Laravel but I really don't know how to do this. I don't know how to rename in FROM like in SQL
My query is the following one :
SELECT f2.* FROM formation f2 WHERE f2.theme_id IN
(SELECT f.theme_id FROM user_formation uf JOIN formation f ON uf.formation_id = f.id WHERE uf.user_id = 2)
AND f2.id NOT IN
(SELECT formation_id FROM user_formation WHERE user_id = 2);
I tried something like this but ...
$q = Formation::query()
->from('formation AS f2')
->whereIn('f2.theme_id', function($r)
{
$r->select('f.theme_id')->from('user_formation AS uf')
->join('formation', function($join)
{
$join->on('uf.formation_id', '=', 'f.id')
->where ('uf.user_id', '=', $id)
});
});
->whereNotIn('f2.id', function($s){
$s->select('formation.id')
->from('user_formation')
->where('user_id', '=', $id)
})->get();
thanks for help.
If you want to run this raw query you can run:
$res = DB::select('
SELECT f2.*
FROM formation f2
WHERE f2.theme_id IN
(SELECT f.theme_id FROM user_formation uf JOIN formation f ON uf.formation_id = f.id WHERE uf.user_id = 2)
AND f2.id NOT IN
(SELECT formation_id FROM user_formation WHERE user_id = 2)');
Or you can rewrite this query in laravel query builder Eloquent ORM:
Formations::query()
->whereIn('formations.theme_id', function($q){
$user_formations_table = (new UserFormation)->getTable();
$formation_table = (new Formation)->getTable();
$q->select('paper_type_id')
->from($user_formations_table)
->join($formation_table, "$user_formations_table.formation_id", '=', "$formation_table.id")
->where("$user_formations_table.user_id", 2);
})->whereNotIn('formations.id', function($q){
$user_formations_table = (new UserFormation)->getTable();
$q->select('formation_id')
->where("$user_formations_table.user_id", 2);
})
->get();
Note that I have used models Formations, UserFormation, Formation Because you have used 3 different tables, you should add this models and specify tables to run ORM query
I advice to run first RAW query if there is no another need to run it with Eloquent
Hope this helps you
First of all, you need to fix your code indentations so you don't confuse yourself. Second, you placed semicolon in the wrong places. Third, you need to pass $id inside function because of the variable scope.
$q = Formation::query()
->whereIn('f2.theme_id', function($r) use ($id) {
$r->select('f.theme_id')->from('user_formation AS uf')
->join('formation', function($join) use ($id) {
$join->on('uf.formation_id', '=', 'f.id')
->where('uf.user_id', '=', $id);
}
);
})
->whereNotIn('f2.id', function($s) use ($id) {
$s->select('formation.id')
->from('user_formation')
->where('user_id', '=', $id);
})->get();
Note : If you are using VSCode, I suggest to use PHP Intelephense as it will help with autocomplete, syntax check, etc.

laravel query building with a lot of joins

my sql query is
$q = "SELECT
file,
roleId,
page,
type,
userType,
COUNT(DISTINCT($a)) as 'a',
COUNT(DISTINCT($b)) as 'b'
FROM table_name
WHERE
course IN ($type)
AND date BETWEEN '$startDate' AND '$endDate'
AND (course_1 is NULL OR course_1 NOT IN ('ABCD'))
AND deleted IS NULL
AND type LIKE '%Professor%'
AND action = 'submit'
GROUP BY file, roleId";
I want to convert that query into laravel query builder like
$orders = DB::table('table_name')
->select('file', 'roleId', 'page', 'type', userType DB::raw('COUNT(DISTINCT(($a)) as 'a'))
->groupBy('file', 'roleId')
->get();
Do understand how to add the other COUNT into it and how and where to chain the ->where() ?
<?php
$orders = DB::table('table_name')
->whereIn('course', $courseTypes)
->whereBetween('date', [$startDate, $endDate])
->where(function($q){
return $q->whereNull('course_1')
->orWhereNotIn('course_1', $courseArrayToFilter);
})
->whereNull('deleted')
->where('type', 'like', '%Professor%')
->where('action', 'submit')
->groupBy('file', 'roleId')
->select(
'file',
'roleId',
'page',
'type',
'userType',
\DB::raw("COUNT(DISTINCT($a)) as a"),
\DB::raw("COUNT(DISTINCT($b) as b")
)
->get();
Maybe in a cleanest way doing this:
Use the Model instance in inspite of invoke the DB facade
Use whereRaw to pass complex or pure SQL queries
Use selectRaw() to process pure SQL queries for instance functions like COUNT
Use Multiple WHERE to emulate AND operator
Use whereIn to filter ranges of data
You need to GROUP BY all columns in your SELECT you have an error at this point, I mean your query is wrong
Code
$data = Model::select('file', 'roleId', 'page', 'type', 'userType')
->selectRaw('COUNT(DISTINCT($a)) as a')
->selectRaw('COUNT(DISTINCT($b)) as b')
->whereRaw('type IN $type')
->whereIn('date', [$startDate, $endDate])
->whereRaw("course_1 IS NULL OR course_1 NOT IN('ABCD')")
->whereNull('deleted')
->where('type', 'LIKE', "%".'Professor'."%")
->where('action', '=', 'submit')
->groupBy('file', 'roleId', 'page', 'type', 'userType')
->get();

Convert Raw SQL query to Laravel DB Query

I have the following raw SQL query:
select a.id user_id, a.email_address, a.name_first, a.name_last, count(b.id) number_of_videos, sum(b.vimeo_duration) total_duration, sum(b.count_watched) total_playbacks
from users a,
videos b
where a.id = b.tutor_id
and a.email_address in ('candace_rennie#yahoo.com', 'tjm#hiltoncollege.com', 'matthewjameshenshall#gmail.com', 'nkululeko#syafunda.co.za', 'khulile#syafunda.co.za', 'nzakheni#syafunda.co.za')
group by a.id;
This correctly gets 6 rows from the database. I'm trying to convert this to a Laravel database query like so:
$totals = DB::table('users')
->select(DB::Raw('users.id as user_id'), 'users.email_address', 'users.name_first', 'users.name_last', DB::Raw('count(videos.id) as number_of_videos'), DB::Raw('sum(videos.vimeo_duration) as total_duration'), DB::Raw('sum(videos.count_watched) as total_playbacks'))
->join('videos', 'users.id', '=', 'videos.tutor_id')
->where('users.id', 'videos.tutor_id')
->whereIn('users.email_address', array('candace_rennie#yahoo.com', 'tjm#hiltoncollege.com', 'matthewjameshenshall#gmail.com', 'nkululeko#syafunda.co.za', 'khulile#syafunda.co.za', 'nzakheni#syafunda.co.za'))
->groupBy('users.id')
->get();
This however return 0 rows. Is there anything I'm missing?
It should be smth like below even tho groupBy user id does not help much as id is unique.
$aggregates = [
DB::raw('count(b.id) as number_of_videos'),
DB::raw('sum(b.vimeo_duration) as total_duration'),
DB::raw('sum(b.count_watched) as total_playbacks'),
];
$simpleSelects = ['users.email_address', users.id, 'users.name_first', 'users.name_last'];
$emails = ['candace_rennie#yahoo.com', 'tjm#hiltoncollege.com'....]
$users = Users::select(array_merge($simpleSelects, $aggregates))
->leftJoin('videos as b', function ($join) use ($emails) {
$join->on('b.tutor_id', 'a.id')
->whereIn('users.email_address', $emails);
})
->groupBy('users.id')
->get();
Try to remove this line:
->where('users.id', 'videos.tutor_id')
List item
after sql code convert into laravel
DB::select('posts.id','posts.title','posts.body')
->from('posts')
->where('posts.author_id', '=', 1)
->orderBy('posts.published_at', 'DESC')
->limit(10)
->get();

Multiple wheres in Laravel join

I have:
$buyingNet = DB::table('parts_enquiries_buying AS PEB')
->select(DB::raw('SUM((PEB.quantity*PEB.net)/IF(ISNULL(currencyRate), rate, currencyRate)) AS total'))
->join('currencies_rates AS CR', function ($q) {
$q->on('CR.id', '=', 'PEB.currencyId')
//->where(DB::raw('YEAR(CR.date)'), '=', date('Y'))
->where(DB::raw('MONTH(CR.date)'), '=', date('m'));
})
->leftJoin('jobs', 'jobs.enquiryId', '=', 'PEB.enquiryId')
->leftJoin('invoices_out AS IO', 'IO.jobId', '=', 'jobs.id')
->where('PEB.enquiryId', $enquiryId)
->first()->total;
If I uncomment the where that matches the year I get null returned, but all the rows that should be there are there.
Is my syntax correct? It should translate as:
... YEAR(CR.date) = ? AND MONTH(CR.date) =? ...
I believe the issue here is that Query builder doesn't understand your DB::raw statement within the ->where clause.
You should do as folllows:
->whereRaw("YEAR(CR.date) = '". date('Y')."'")
->whereRaw("MONTH(CR.date) = '". date('n')."'")
for the month clause you need to use n instead of m since MySQL MONTH returns a single digit for months below 10.

mysql join ON and AND to laravel eloquent

I've been able to get the query result I need using the following raw sql:
select `person`.`id`, `full_name`, count(actions.user_id) as total
from `persons`
left join `actions`
on `actions`.`person_id` = `persons`.`id`
and `actions`.`user_id` = $user
where `type` = 'mp'
group by `persons`.`id`
But I haven't been able to get it working in eloquent yet.
Based on some similar answers, I'd tried functions within ->where() or leftJoin(), but the count of each person's actions isn't yet being filtered by $user. As it stands:
$query = Person::leftJoin('actions', function($q) use ($user)
{
$q->on('actions.person_id', 'persons.id')
->where('actions.user_id', $user);
})
->groupBy('persons.id')
->where('type', 'foo')
//->where('actions.user_id', '=', $user)
->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);
I'm at least heading in roughly the right direction, right...?
If it's relevant, the Persons.php model has two actions relationships:
public function actions()
{
return $this->hasMany('Action');
}
public function actionsUser($id)
{
return $this->hasMany('Action')->where('user_id', $id);
}
So, for reference, I solved it like so:
$query = Person::leftJoin('actions', function($q) use ($user)
{
$q->on('actions.person_id', '=', 'persons.id')
->where('actions.user_id', '=', "$user");
})
->groupBy('persons.id')
->where('type', 'foo')
->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);
The ->where() clause within leftJoin, oddly, needs the speech marks for the variable to be passed through the sql query correctly (likewise, '2' doesn't seem to work while "2" does).
I found that the where doesn't always work on the leftJoin clause
If in the future you get any trouble with it, I'd suggest you using this:
$query = Person::leftJoin('actions', function($q) use ($user)
{
$q->on('actions.person_id', '=', 'persons.id')
->on('actions.user_id', '=', "$user");
})
->groupBy('persons.id')
->where('type', 'foo')
->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);
Hope it helps someone.
When laravel eloquent just start getting complex like this
For more flexibility and readability I'll just use plain sql statement then hydrate the results.
$sql = "
SELECT `person`.`id`,
`full_name`,
count(actions.user_id) AS total
FROM `persons`
LEFT JOIN `actions`
ON `actions`.`person_id` = `persons`.`id`
AND `actions`.`user_id` = $user
WHERE `type` = 'mp'
GROUP by `persons`.`id`
";
$query = Person::hydrate(
DB::select( $sql )
);