I have written a sql query using Laravel, but I am not understanding, why the error is creating! The codes are given below,
The join operation:
MeetingRoom::select('mr_id')
->leftJoin('meetingroomhistory',function($join)
{
$join->on('country','=',Session::get('country'));
$join->on('location','=',Session::get('location'));
$join->on('building','=',Session::get('building'));
$join->on('floor','=',Session::get('floor'));
$join->on('name_of_mr','=',Session::get('room'));
})
->where('meetingroom.id','=','meetingroomhistory.mr_id')
->get();
The error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Bangladesh' in
'on clause' (SQL: select `mr_id` from `meetingroom` left join
`meetingroomhistory` on `country` = `Bangladesh` and `location` =
`Dhaka` and `building` = `Uttara` and `floor` = `3` and `name_of_mr` =
`1` where `meetingroom`.`id` = meetingroomhistory.mr_id)
But if I run the query manually to change this syntax `Bangladesh` to "Bangladesh" using phpmyadmin so it runs well and show me the result. Please someone let me know, how can I fix it?
I think you've confused the where part and the join part.
$join->on($x, $y) statements are for connecting your tables together. Both $x and $y should be names of columns in your tables - that is why Laravel is adding backticks to them.
$where() statements are for comparing with values that you supply. Your Session::get() calls indicate that's what you're doing.
Here's a suggested rewrite, but it may need to be tweaked to suit your exact needs.
MeetingRoom::select('mr_id')
->leftJoin('meetingroomhistory', 'meetingroom.id', '=', 'meetingroomhistory.mr_id')
->$where('meetingroom.country','=',Session::get('country'))
->$where('meetingroom.location','=',Session::get('location'))
->$where('meetingroom.building','=',Session::get('building'))
->$where('meetingroom.floor','=',Session::get('floor'))
->$where('meetingroom.name_of_mr','=',Session::get('room'))
->get();
I assumed the country, location, etc. columns are part of the meetingroom table, if not you can just change them to $where('meetingroomhistory.country', ...) and so on instead.
Finally, I'm not sure why you're selecting only one value, but of course, that's up to you. If you need only a single cell, you can use pluck(), and if you need a lot of single results you could do lists().
I think you should try this.
MeetingRoom::select('mr_id')
->join('meetingroomhistory', function($join)
{
$join->on('meetingroom.id','=','meetingroomhistory.mr_id')
->where('meetingroomhistory.country','=',Session::get('country'));
->where('meetingroomhistory.location','=',Session::get('location'));
->where('meetingroomhistory.building','=',Session::get('building'));
->where('meetingroomhistory.floor','=',Session::get('floor'));
->where('meetingroomhistory.name_of_mr','=',Session::get('room'));
})
->get();
Related
I am trying Laravel join query to select the column dynamically but below line is returning error.
\DB::raw('table3.ElrA'.($effectiveYear'.-YEAR(table1.eff_date).'))
table3 having columns like this ElrA1, ElrA2 .....
common part is "ElrA" I am just making trailing number dynamically to create whole column name but it gives me err like "ElrA202-YEAR(table3.eff_date) is not a column". can you please suggest any solutions.
$query = DB::table('table1')
->join('table2', function($join) {
$join->on('table2.policy_period_id', '=', 'table1.id');
$join->where('status','1');
})
->leftjoin('table3', function($join) use($effective_date)
{
$join->on('table3.class_code', '=', 'table2.code');
$join->where('table3.date', '=', DB::raw("(select max(`date`) from table3 where date <= '".$effective_date."' limit 1)"));
})
->select(\DB::raw('table3.ElrA'.($effectiveYear'.-YEAR(table1.eff_date).')))
->where('table1.mod_id',$id);
Thanks
When you look at the error code, it says clearly that laravel try to find column ElrA202-YEAR(table3.eff_date)
What happen is because you make mistake in this part
'table3.ElrA'.($effectiveYear'.-YEAR(table1.eff_date).'
the exact part is in this one
'.-YEAR(table1.eff_date).'
because you use '' and it will parsed as string and not the variable that you want
I don't know why you will use dynamic column, but it is really not a good idea, because as the documentation says, it's very vulnerable with sql injection attack because there is no parameter binding in dynamic column. But if you know what you are doing then it's okay
Background
I have written a SQL query that works perfectly for my needs, and I am trying to add it to a queued job in Laravel. Instead of using Eloquent models I wanted to go with DB Query to ensure better performance as there will ultimately be many joins and conditions. I am having a problem with the where clause when checking a date, but it works perfectly fine when running in SQL. I have stripped out additional pieces of this query to only include what is necessary for debugging this issue.
Code
The original SQL:
SELECT `messages`.`created_at`, `participants`.`last_read`
FROM `messages`
LEFT JOIN `participants` ON `messages`.`thread_id` = `participants`.`thread_id` AND `messages`.`user_id` != `participants`.`user_id`
WHERE `messages`.`created_at` > `participants`.`last_read`;
When I run this directly in SQL, I see 2 results, which is expected with my current data.
created_at
last_read
2021-03-26 19:02:53
2021-03-23 19:31:30
2021-03-26 19:02:58
2021-03-23 19:31:30
This is how I have written it in Laravel:
$query = DB::table('messages')
->leftJoin('participants', function ($join) {
$join->on('messages.thread_id', '=', 'participants.thread_id')
->on('messages.user_id', '!=', 'participants.user_id');
})
->select('messages.created_at as message_date', 'participants.last_read as last_read')
->where('messages.created_at', '>', 'participants.last_read');
When I execute this, the results are empty.
I dumped the final SQL from the DB Query builder to make sure it's correct, and this is what it is:
select `messages`.`created_at` as `message_date`, `participants`.`last_read` as `last_read`
from `messages`
left join `participants`
on `messages`.`thread_id` = `participants`.`thread_id` and `messages`.`user_id` != `participants`.`user_id`
where `messages`.`created_at` > participants.last_read
And running that directly in SQL returns accurate results, as expected.
Context
For context, here is the data structure and some of the data I'm working with.
participants
id
thread_id
user_id
last_read
created_at
updated_at
deleted_at
last_notified
9
8
178
2021-03-23 23:31:53
2021-03-23 22:16:48
2021-03-23 23:31:53
NULL
NULL
messages
id
thread_id
user_id
body
created_at
updated_at
deleted_at
159
3
177
adfad
2021-03-26 19:02:53
2021-03-26 19:02:53
NULL
160
3
177
dadddda
2021-03-26 19:02:58
2021-03-26 19:02:58
NULL
The problem
It seems as though the DB query code is causing the columns with like names to be mixed up. Both tables have a column called created_at, but I only need that column from the messages table. My SELECT only asks for that column, specifying the correct table. But something in this DB Query join is causing it to get mixed up.
Playing with different joins, and removing the where clause, I realized that the dates aren't correct always. For example, here is the result when I use leftJoin
{
"message_date": "2021-03-23 00:30:42",
"last_read": "2021-03-26 00:22:48"
},
{
"message_date": "2021-03-23 00:31:25",
"last_read": "2021-03-26 00:22:48"
}
Notice, the message_date and last_read values are reverse of what they were when running the SQL directly. So this must be the problem.
I changed to rightJoin, and the results are reversed:
{
"message_date": "2021-03-26 19:02:53",
"last_read": "2021-03-23 19:31:30",
},
{
"message_date": "2021-03-26 19:02:58",
"last_read": "2021-03-23 19:31:30",
}
So that should work, right? I add the where clause back in, but still the results are empty.
I am guessing there is something I need to do to tell the query builder to handle these columns correctly, as they seem to be getting mixed up during the where and select. But I can't figure out how to clarify that. I have tried searching for others with this issue but I can't seem to find anything relevant.
Already tried
I have already tried a few things with no change in results.
Changing the order of the commands - like moving the select() to the beginning of the statement, things like this.
Using whereDate instead of where. (Note - for performance I'd rather avoid this, but wanted to try just in case).
Using join, joinLeft, and joinRight.
Using where in the on clause instead of two ons. Like this
->leftJoin('participants', function ($join) {
$join->on('messages.thread_id', '=', 'participants.thread_id')
->where('messages.user_id', '!=', 'participants.user_id');
})
Anyone have any guidance on things I can try? This should be such a simple task, and has turned into hours of trying to understand why it works in SQL and not Laravel's DB Query Builder.
The where function of the query builder will always assume the right hand side is a value and will use it in a prepared statement as a literal (in this case string). If you want to compare columns you need to use whereColumn:
$query = DB::table('messages')
->leftJoin('participants', function ($join) {
$join->on('messages.thread_id', '=', 'participants.thread_id')
->on('messages.user_id', '!=', 'participants.user_id');
})
->select('messages.created_at as message_date', 'participants.last_read as last_read')
->whereColumn('messages.created_at', '>', 'participants.last_read')->get();
Additional where clauses can be found in the docs
I am trying to figure out why is DB::raw() queries are getting sent as lowercases?
Query = DB::('table_name')->select(['is_read as isRead'])->get();
Result = [{ isRead: true }]
But when I do raw its converting it to lowercase
Query = DB::('table_name')->select(DB::raw('is_read as isRead'))->get();
Result = [{ isread: true }]
I have a reason to use DB raw so I really need to figure this thing out.
I'm not able to reproduce the issue you mention... Which version of Laravel are you using?
For instance, if I run the following:
DB::table('users')->select(DB::raw('is_read as isRead'))->get();
I would get the error:
Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'is_read' in 'field list' (SQL: select is_read as isRead from users)'
Which is normal because I have no is_read column in my users table. However, you can see in the error that the isRead is not converted to lowercase.
Maybe you can use selectRaw instead:
DB::table('table_name')->selectRaw('is_read as isRead')->get();
The query would be:
select is_read as isRead from `table_name`
Otherwise, could you update your question to provide more information on how to reproduce so your issue with the capitalization.
I can confirm that when using DB:raw (or orderByRaw or any row raw methods) column names get converted to lowercase.
To avoid that, you can try to protect the name with quotes:
Query = DB::('table_name')->select(['is_read as "isRead"'])->get();
I have the following query which I'm trying to convert into Laravel's query builder so I can take advantage of automatic escaping etc.
SELECT subjects.name, report_comments.comment
FROM subjects
LEFT JOIN (report_comments, library_comments) ON subjects.id = library_comments.subject_id
AND report_comments.library_comment_id = library_comments.id
AND report_comments.report_id = 1
Effectively what the query says is 'get the names of all the subjects, and if they have a matching report_comment (via the intermediate library_comments table), return that along with the subject' (a subject has either one or zero report_comments for the given criteria). The query works if I run it directly in MySQL and returns the results I'd expect. The report_comment.report_id = 1 is hard-coded at the moment but will eventually be a placeholder so that any report_id can be passed in.
So far I've managed to get:
DB::table('subjects')->select(['subjects.name', 'report_comments.comment'])->leftJoin('report_comments', function ($join) {
$join->on('subjects.id', '=', 'library_comments.subject_id')
->on('report_comments.library_comment_id', '=', 'library_comments.id')
->on('report_comments.report_id', '=', '1');
})
If I add toSql the result is:
select `subjects`.`name`, `report_comments`.`comment` from `subjects` left join `report_comments` on `subjects`.`id` = `library_comments`.`subject_id` and `report_comments`.`library_comment_id` = `library_comments`.`id` and `report_comments`.`report_id` = `1`
This is almost what I want, except it fails because the library_comments table is not mentioned at all:
Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'library_comments.subject_id' in 'on clause' (SQL: select `subjects`.`name`, `report_comments`.`comment` from `subjects` left join `report_comments` on `subjects`.`id` = `library_comments`.`subject_id` and `report_comments`.`library_comment_id` = `library_comments`.`id` and `report_comments`.`report_id` = `1`)'
What I need to do is tell the leftJoin function about report_comments and library_comments, but there doesn't seem to be any way to do this. I tried:
leftJoin(['report_comments', 'library_comments'], function($join)
on a guess that Laravel might convert an array of table names into (report_comments, library_comments), but that didn't work and gave me the following warning:
PHP Notice: Array to string conversion in /home/paul/sites/report-assistant/vendor/laravel/framework/src/Illuminate/Database/Grammar.php on line 39
Is there a way to pass multiple tables into leftJoin, or do I need to completely rewrite the query in order to work with Laravel's query builder?
I'm using laravel/framework version 5.8.21 and all my dependencies are up to date (composer update && npm update).
Use BD::raw
write query like this and It will work
DB::table('subjects')->select(['subjects.name, report_comments.comment'])->leftJoin(DB::raw('(report_comments, library_comments)'), function ($join) {
$join->on('subjects.id', '=', 'library_comments.subject_id')
->on('report_comments.library_comment_id', '=', 'library_comments.id')
->on('report_comments.report_id', '=', '1');
})
Not sure if this will work but i assume it will be somthing along these lines, hopefully you get something out of it.
Basically added a check to see if the relationship exists if it does then join it.
Subject::select('subjects.name, report_comments.comment')
->leftJoin('library_comments', 'subjects.id, '=', library_comments.subject_id')
->leftJoin('report_comments', function($join){
if(report->library->relationship){
$join->on('report_comments.library_comment_id', '=', 'library_comments.id')
->where('report_comments.report_id', '=', '1');
}
})
After a bit of tinkering, I managed to find the answer in two parts:
First, I had to tweak this part of the join:
on('report_comments.report_id', '=', '1')
and replace it with:
where('report_comments.report_id', '=', '1')
If I didn't do this, Laravel would quote 1 with backticks, causing MySQL to interpret it as a column name.
The other change was to use DB::raw, which I was trying to avoid but I don't think it's too bad in this situation because I'm passing a hardcoded string rather than user input (or anything influenced by user input). The leftJoin now looks like:
leftJoin(DB::raw('(report_comments, library_comments)')
Can someone help me to convert the below mysql to laravel db query builder or eloquent?Here is my mysql
SELECT max(created_at), jobseeker_id,call_reason,type_of_call
FROM calllogs
GROUP BY jobseeker_id
ORDER BY created_at DESC;
Here is my tries, but no luck yet.
$jobseekers =DB::table('calllogs')
->select(DB::raw("max('created_at'),jobseeker_id"))
->groupBy('jobseeker_id')
->orderBy('created_at','desc')
->get();
dd($jobseekers);
Please help me out.
$jobseekers =DB::table('calllogs')
->select(DB::raw("max(created_at),jobseeker_id"))
->groupBy('jobseeker_id')
->orderBy('created_at','desc')
->get();
Try with this code.
Only delete ' ' in max.
It will work well.
DB::table(calllogs)
->select(DB::raw('max(created_at) as max_created_at'),
'jobseeker_id','call_reason','type_of_call')
->groupBy('jobseeker_id')
->orderBy('max_created_at', 'DESC')
->get(); =>As a array.
->first(); => As a object.
Additionally, If you are using table joins see below.
->join('table_1','table_1.id','=','table_2.table_1_id')
->leftjoin('table_1','table_1.id','=','table_2.table_1_id')
->rightjoin('table_1','table_1.id','=','table_2.table_1_id')
ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'myapp.calllogs.created_at'
Two solution for that error
1.In config/database.php file make sql strict mode to false.
(or)
2. IN groupBy Clause add all your table colums.
example:
->groupBy('jobseeker_id','jobseeker_name','jobseeker_email')