Comparing timestamps from two different tables in Laravel 5 - php

I am trying to get results out of union by showing only results that were updated after I last checked (defined by $last_check)
$last_check = CheckNotifications::where('notif_check_user_id', '=', $user_id)->pluck('updated_at');
$get_projects = DB::table('requests')
->join('notifications', 'notifications.notif_project_id', '=', 'requests.id')
->select(DB::raw('requests.updated_at, requests.request_name, "" as fullname, "P" as flag'))
->where('notif_user_id', '=', $user_id)
->whereRaw('requests.updated_at > requests.created_at');
$comments = DB::table('project_comments')
->leftJoin('users', 'comment_user_id', '=', 'users.id')
->leftJoin('requests', 'comment_project_id', '=', 'requests.id')
->select(DB::raw('project_comments.updated_at, requests.request_name, users.fullname, "C" as flag'));
$get_notifications = $get_projects->union($comments)
->whereRaw('updated_at > $last_check')
->orderBy('updated_at', 'desc')
->get();
The union works just fine until I add that last whereRaw statement. With the statement added, I get a SQL Syntax/Access error (#42000). I think it has something todo with the plucking of updated_at for the comparison. Any ideas? Thanks in advance!
Edit: Here's the error code
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '15:09:06) union (select project_comments.updated_at, requests.id as request_id, ' at line 1 (SQL: (select requests.updated_at, requests.id as request_id, requests.request_name, "" as fullname, "P" as flag from `requests` inner join `notifications` on `notifications`.`notif_project_id` = `requests`.`id` where `notif_user_id` = 1 and requests.updated_at > requests.created_at and requests.updated_at > 2015-07-29 15:09:06) union (select project_comments.updated_at, requests.id as request_id, requests.request_name, users.fullname, "C" as flag from `project_comments` left join `users` on `comment_user_id` = `users`.`id` left join `requests` on `comment_project_id` = `requests`.`id`) order by `updated_at` desc)

there whould be 2 updated_at column , Please attach your error while mentioning something like that again I can't be sure of the reason.
the solution is simply to write the table name before the column name
change
->whereRaw('updated_at > $last_check')
into
->whereRaw('requests.updated_at > $last_check')
and change orederby() to be after the whereRaw()
you had written the right code just few lines before :D
I hope this solve your problem

add that whereRaw clause for each of previous two queries
->where('requests.updated_at','>', $last_check)
or
->whereRaw('requests.updated_at > ?', [$last_check])
probably where is not available with union
just curious : if this is working?
$get_notifications = $get_projects->union($comments)
->where(function($query) use ($last_checked){
$query ->where('requests.updated_at','>', $last_check);
})
->orderBy('requests.updated_at', 'desc')
->get();

Related

Why am is laravel throwing an SQLSTATE[42000]: Syntax error or access violation: 1064 Error

Am running a query builder on my laravel app using inner join
But Laravel keeps throwing errors, i tested the MySql Query
i wrote directly in my database using phpMyAdmin it works fine
SELECT
u.id, u.first_name, u.last_name, u.username, u.sponsor,u.deleted_at, i.id as investment_id, i.total_amount, i.created_at
FROM
users AS u
JOIN investments as i ON
i.id= ( SELECT i1.id FROM investments as i1 where u.id=i1.user_id and i1.status ='confirmed' ORDER BY i1.created_at LIMIT 1)
WHERE
u.sponsor = '901d08da-e6c4-476a-ae7b-9386990b8b9e' AND u.deleted_at is NULL
ORDER BY
created_at DESC
but when i write it using query builder it wont work.
$refered_users = DB::table('users')
->join('investments', function ($join) {
$join->on('users.id', '=', 'investments.user_id')
->where('investment.status', '=', 'confirmed')
->orderBy('investment.created_at','desc')->first();
})
->select('users.id,users.first_name,users.last_name,users.username,users.sponsor,investment.id AS investment_id,investment.total_amount,investment.created_at')
->where('users.sponsor','=',Auth::User()->id)
->orderBy('investment.created_at','desc')
->paginate(10);
i tried a RAW DB::select() and it works but i want to use the query builder so i can paginate the results.
this is how my table is arranged:
users
id, first_name, last_name, username, sponsor(id of another user), created_at, deleted_at
investments
id, total_amount , user_id(id of a user), status, created_at, deleted_at
Am not much Good with SQL Queries so if am writing it all wrong please don't scold just, try to explain a lil bit more so i can understand
this is the error coming out:
Illuminate\Database\QueryException
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'on users.id = investments.user_id and
investment.status = ? order by' at line 1 (SQL: select * on
users.id = investments.user_id and investment.status =
confirmed order by investment.created_at desc limit 1)
output of the dd
select first_name,last_name,username,deleted_at,total_amount,
investment_created_at,user_id from `users`
inner join (select user_id,total_amount,status,created_at AS investment_created_at from `investments`
where `status` = ? and `investments`.`deleted_at` is null) as `confirmed_investments`
on `users`.`id` = `confirmed_investments`.`user_id`
where `sponsor` = ? order by `investment_created_at` desc ◀`
`array:2 [▼ 0 => "confirmed" 1 => "901d08da-e6c4-476a-ae7b-9386990b8b9e" ]`
am using:
PHP version: 7.3.1
MySql Version: 8.0.18
You can get query of your code and compare it to your desired query like this:
$refered_users = DB::table('users')
->join('investments', function ($join) {
$join->on('users.id', '=', 'investments.user_id')
->where('investment.status', '=', 'confirmed')
->orderBy('investment.created_at','desc')->first();
})
->select('users.id,users.first_name,users.last_name,users.username,users.sponsor,investment.id AS investment_id,investment.total_amount,investment.created_at')
->where('users.sponsor','=',Auth::User()->id)
->orderBy('investment.created_at','desc')
->toSql();
Your join query is getting data for id by running another query. I think you need to use sub query. If you are using laravel > 6 it is on documentation.

Laravel: MYSQL query in laravel

I have a working query goes like this
SELECT s.name as status, q.name as quality, p.name process, count(*)
FROM plates
JOIN equipment_status_codes s on equipment_status_code_id = s.id
JOIN plate_qualities q on plate_quality_id = q.id
JOIN processes p on process_id = p.id WHERE project_id in
(SELECT id
from projects
WHERE name like 'SPIRIT')
GROUP BY s.name, q.name, p.name ASC with ROLLUP
This works just and returns results just fine.
Now I am trying to put this in laravel syntax, but having some difficulties.
So I was thinking something along these lines.
return Plate::select('equipment_status_codes.name as Status', 'plate_qualities.name as Quality', 'processes.name as Process')
->join('equipment_status_codes', 'plates.equipment_status_code_id', '=', 'equipment_status_codes.id')
->join('plate_qualities', 'plates.plate_quality_id', '=', 'plate_qualities.id')
->join('processes', 'plates.process_id', '=', 'processes.id')
->groupBy(DB::raw('equipment_status_code_id WITH ROLLUP'))
...
...
->get();
Would someone help out. Thanks in advance!
Update:
#Govind Samrow
I have tried this query. It works (with couple of small adjustment) But I am not getting the same results as the one I get when I run the sql query.
I included screen shots.
So when I run the sql query.
I get the following results.
When I run the laravel query.
return DB::table('plates')
->join('equipment_status_codes', 'equipment_status_code_id', '=', 'equipment_status_codes.id')
->join('plate_qualities', 'plate_quality_id', '=', 'plate_qualities.id')
->join('processes', 'process_id', '=', 'processes.id')
->whereRaw("project_id IN(SELECT id from projects WHERE name like 'SPIRIT')")
->select(DB::raw('equipment_status_codes.name as Status'), DB::raw('IFNULL(plate_qualities.name, NULL) as Quality'), DB::raw('IFNULL(processes.name, NULL) as process'), DB::raw("COUNT(*) as Total" ))
->groupBy(DB::raw('equipment_status_codes.name WITH ROLLUP', 'plate_qualities.name WITH ROLLUP', 'processes.name WITH ROLLUP', 'asc'))
->get();
I get the following.
Almost there, but I am not sure what's going on?! Any ideas?
Try following Query for Joining with where Condition
return Plate::select('equipment_status_codes.name as Status', 'plate_qualities.name as Quality', 'processes.name as Process')
->join('equipment_status_codes', 'plates.equipment_status_code_id', '=', 'equipment_status_codes.id')
->join('plate_qualities', 'plates.plate_quality_id', '=', 'plate_qualities.id')
->join('processes', function($join)
{
$join->on('plates.process_id', '=', 'processes.id')
->whereIn('project_id', DB::table('projects')->where('name','LIKE','SPIRIT')->select('id')->get()->toArray());
})
->groupBy(DB::raw('equipment_status_code_id WITH ROLLUP'))
->get();
Hope this will help.
Use whereRaw for sub query in where clause Try this:
DB::table('plates')
->join('equipment_status_codes', 'equipment_status_code_id', '=', 'equipment_status_codes.id')
->join('plate_qualities', 'plate_quality_id', '=', 'plate_qualities.id')
->join('processes', 'process_id', '=', 'processes.id')
->whereRaw("project_id IN(SELECT id from projects WHERE name like 'SPIRIT')")
->select('equipment_status_codes.name as status', 'plate_qualities.name as quality', 'q.name as quality', 'processes.name as Process', DB::raw("COUNT(*) as Total"))
->groupBy(DB::raw('equipment_status_codes.name, plate_qualities.name, processes.name ASC with ROLLUP'))->get();
Here is raw sql result of above that got with toSql():
select `equipment_status_codes`.`name` as `status`, `plate_qualities`.`name` as `quality`, `q`.`name` as `quality`,
`processes`.`name` as `Process`, COUNT(*) as Total from `plates`
inner join `equipment_status_codes` on `equipment_status_code_id` = `equipment_status_codes`.`id`
inner join `plate_qualities` on `plate_quality_id` = `plate_qualities`.`id`
inner join `processes` on `process_id` = `processes`.`id`
where project_id IN(SELECT id from projects WHERE name like 'SPIRIT')
group by equipment_status_codes.name, plate_qualities.name, processes.name ASC with ROLLUP
Note: You can use SQL output with $query->toSql() and then compare with your actual SQL query.
You may use the table method on the DB facade to begin a query. The table method returns a fluent query builder instance for the given table, allowing you to chain more constraints onto the query and then finally get the results using the get method:
Check its link and get knowladge for laravel query builder:-
https://laravel.com/docs/5.4/queries

How to write mysql query in laravel 5.4?

I am new to laravel and i want to write mysql query in laravel 5.4.
query is like :
note: avoid column names..
SELECT *
FROM (SELECT DISTINCT *
FROM messages
WHERE (from_id=1 OR to_id=1)
ORDER BY created DESC) as m
GROUP BY `from_id`
I tried but gives error.
$messages = DB::table('messagetbl')
->select('*')
->Where(function($query) use ($userid){
$query->distinct()
->where('senderid',$userid)
->orWhere('receiverid',$userid)
->orderBy('datetime','desc');
})
->groupBy('senderid')
->get();
Error:
SQLSTATE[42000]: Syntax error or access violation: 1055
Expression #1 of SELECT list is not in GROUP BY clause and contains
nonaggregated column 'db.messagetbl.id' which is not functionally
dependent on columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by (SQL: select * from messagetbl where
(senderid = 8 or receiverid = 8) group by senderid)
Thanks in advance.
I believe something like this:
DB::table('messages')
->select('*')
->where('form_id', '=', 1)
->orWhere('to_id', '=', 1)
->orderBy('created', 'desc')
->groupBy('form_id')
->distinct()
->get();

Laravel query builder: error in mysql where clause

Here is my join query
$data['userslist'] = DB::table('users')
->select('users.*','user_roles.role_name')
->join('user_roles','users.user_type=user_roles.role_id')
->where('users.user_type','!=',1)
->get();
But i will get the following error in where clause
check the manual that corresponds to your MariaDB server version for
the right syntax to use near 'where `users`.`user_type` != ?' at
line 1 (SQL: select `users`.*, `user_roles`.`role_name` from `users`
inner join `user_roles` on `users`.`user_type=user_roles`.`role_id`
where users.user_type != 1)
You try to fetch users.user_type where value in not equal to 1. For this, you need to use '<>' in where clause
Now your query is as follow :
$data['userslist'] = DB::table('users')
->select('users.*','user_roles.role_name')
->join('user_roles', 'users.user_type', '=', 'user_roles.role_id')
->where('users.user_type','<>',1)
->get();
I hope you will get your solution.

Different results using same query with DB::raw and Eloquent

I'm getting some unexpected results when running an Eloquent join query. I get two different results from using the exact same query. One running with DB::raw(), the second with Eloquent.
In the Eloquent query, the Users that matches the
where squad_user.leave_time >= seasons.start_time
are missing and will not be included in the result set. The users that matches the
or squad_user.leave is null
will be included, however.
That's the only difference in the results from the two queries. The raw query actually produces the desired result set.
What really puzzles me is, if I check the query logs, both Laravel's and MySQL, I get the exact same query when running both the raw and Eloquent query.
Raw query (the actual query i get from the query log when running the Eloquent query)
return \DB::select(\DB::raw('
select users.*
from users
inner join squad_user on users.id = squad_user.user_id
inner join seasons on squad_user.squad_id = seasons.squad_id
where squad_user.join_time <= seasons.end_time
and (squad_user.leave_time >= seasons.start_time or squad_user.leave_time is null)
and seasons.id = :seasonId
'),
['seasonId' => 3]
);
Eloquent query
return User::join('squad_user', 'users.id', '=', 'squad_user.user_id')
->join('seasons', 'squad_user.squad_id', '=', 'seasons.squad_id')
->where('squad_user.join_time', '<=', 'seasons.end_time')
->where(function ($query)
{
$query->where('squad_user.leave_time', '>=', 'seasons.start_time')
->orWhereNull('squad_user.leave_time');
})
->where('seasons.id', 3)
->get(['users.*']);
Laravel's Eloquent query log
select `users`.*
from `users`
inner join `squad_user` on `users`.`id` = `squad_user`.`user_id`
inner join `seasons` on `squad_user`.`squad_id` = `seasons`.`squad_id`
where `squad_user`.`join_time` <= seasons.end_time
and (`squad_user`.`leave_time` >= seasons.start_time or `squad_user`.`leave_time` is null)
and `seasons`.`id` = 3
{"bindings":["seasons.end_time","seasons.start_time",3],"time":0.38,"name":"mysql"}
MySQL's general_log on the Eloquent query
select `users`.*
from `users`
inner join `squad_user` on `users`.`id` = `squad_user`.`user_id`
inner join `seasons` on `squad_user`.`squad_id` = `seasons`.`squad_id`
where `squad_user`.`join_time` <= ?
and (`squad_user`.`leave_time` >= ? or `squad_user`.`leave_time` is null)
and `seasons`.`id` = ?
MySQL's general_log on the Raw query
select users.*
from users
inner join squad_user on users.id = squad_user.user_id
inner join seasons on squad_user.squad_id = seasons.squad_id
where squad_user.join_time <= seasons.end_time
and (squad_user.leave_time >= seasons.start_time or squad_user.leave_time is null)
and seasons.id = ?
I would appreciate any pointers here, as I am very lost.
where binds 3rd param and treats it usually as a string, unless you tell it not to by using raw statement. DB::raw or whereRaw will work for you:
return User::join('squad_user', 'users.id', '=', 'squad_user.user_id')
->join('seasons', 'squad_user.squad_id', '=', 'seasons.squad_id')
->where('squad_user.join_time', '<=', DB::raw('seasons.end_time'))
->where(function ($query)
{
$query->where('squad_user.leave_time', '>=', DB::raw('seasons.start_time'))
->orWhereNull('squad_user.leave_time');
})
->where('seasons.id', 3)
->get(['users.*']);
Since Laravel Verion 5.2 you can also use whereColumn to verify that two columns are equal (or pass a comparison operator to the method):
->whereColumn('squad_user.join_time', '<=', 'seasons.end_time')

Categories