how would I go about writing this SQL query in Laravel 4.2 using eloquent?
SELECT *
FROM participants
WHERE user_id IN (1, 2)
GROUP BY convo_id
HAVING count(DISTINCT user_id) = 2
AND count(DISTINCT convo_id) = 1
I tried this already
Participant::whereIn('user_id', $participantIds)
->groupBy('convo_id')
->havingRaw('count(DISTINCT user_id) = '. sizeof($participantIds))
->whereRaw('count(DISTINCT convo_id) = 1')
->get();
But I get this error
SQLSTATE[HY000]: General error: 1111 Invalid use of group function (SQL: select * from `participants` where `user_id` in (1, 2, 4) and count(DISTINCT convo_id) = 1 group by `convo_id` having count(DISTINCT user_id) = 3)
My mistake. whereRaw should also be havingRaw.
Participant::whereIn('user_id', $participantIds)
->groupBy('convo_id')
->havingRaw('count(DISTINCT user_id) = '. sizeof($participantIds))
->havingRaw('count(DISTINCT convo_id) = 1')
->get();
Try groupBy at last
Participant::whereIn('user_id', $participantIds)
->havingRaw('count(DISTINCT user_id) = '. sizeof($participantIds))
->whereRaw('count(DISTINCT convo_id) = 1')
->groupBy('convo_id')
->get();
Related
I have users, conversations, conversation_user and messages table:
Before making a new conversation with $data array of user id's, I am trying to find existing one:
$data = [2,3]; // without auth()->id() -> 1 => total of 3 users per conversation
auth()->user()->conversations()->has('messages')->whereHas('users', function ($query) use ($data) {
$query->whereIn('user_id', $data);
})->whereHas('users', function ($query) use ($data) {
$query->groupBy('conversation_id', 'conversation_user.id')
->havingRaw('count(conversation_id) = ' . count($data) + 1); // total count is 3
})->first()
Now first whereHas returns even if I have conversation between auth()->id() and ID-2, because user_id 2 is in (2,3).. So it would retrieve the wrong conversation, where I need to count for users per conversation as well.
The second whereHas is for counting however if I use $query->groupBy('conversation_id') I get mysql SQL_MODE error for grouping, meaning I need to add $query->groupBy('conversation_id', 'conversation_user.id') as well, but with all that I get no record from database even if there are some.
What am I missing here?
[Updated with generated sql]
select * from `conversations`
inner join `conversation_user` on `conversations`.`id` = `conversation_user`.`conversation_id`
where `conversation_user`.`user_id` = 1 and exists (
select * from `conversation_messages`
where `conversations`.`id` = `conversation_messages`.`conversation_id`
and `conversation_messages`.`deleted_at` is null
) and exists (
select * from `users`
inner join `conversation_user` on `users`.`id` = `conversation_user`.`user_id`
where `conversations`.`id` = `conversation_user`.`conversation_id`
and `user_id` in (2, 3) and `users`.`deleted_at` is null
) and exists (
select * from `users`
inner join `conversation_user` on `users`.`id` = `conversation_user`.`user_id`
where `conversations`.`id` = `conversation_user`.`conversation_id`
and `users`.`deleted_at` is null
group by `conversation_id`, `conversation_user`.`id`
having count(conversation_id) = 3
) and `conversations`.`deleted_at` is null
[Update with table structures]
users -> id, name, email
conversations -> id, slug, subject
conversation_user -> id, user_id, conversation_id
messages -> id, conversation_id, user_id, body
[Another update]
Seems like this works also, in case someone need:
auth()->user()->conversations()->has('messages')->whereHas('users', function ($query) use ($data) {
$query->whereIn('user_id', $data);
})->whereDoesntHave('users', function ($query) use ($data) {
$query->whereNotIn('user_id', $data);
})->first()
I think this is the SQL you want -
SELECT c.*
FROM conversation_user cu
JOIN conversations c
ON cu.conversation_id = c.id
WHERE cu.user_id IN (1, 2, 3)
AND NOT EXISTS (
SELECT *
FROM conversation_user
WHERE conversation_id = cu.conversation_id
AND user_id NOT IN (1, 2, 3)
)
GROUP BY cu.conversation_id
HAVING COUNT(DISTINCT cu.user_id) = 3
Not sure if this is correct as I am not a Laravel user -
$data = [1, 2, 3];
$conv = DB::table('conversation_user cu')
->select('c.*')
->join('conversations c', 'cu.conversation_id', '=', 'c.id')
->whereIn('cu.user_id', $data)
->whereNotExists(function($query) use ($data) {
$query->select(DB::raw(1))
->from('conversation_user')
->whereColumn('conversation_id', 'cu.conversation_id')
->whereNotIn('user_id', $data);
})
->groupBy('cu.conversation_id')
->havingRaw('COUNT(DISTINCT cu.user_id) = ?', count($data))
->get();
select * from `eplan_vacancy` where `reference_id` in
(select `eplan_ep_details`.`reference_id`
from `eplan_ep_details`
inner join `eplan_court_cases` on `eplan_ep_details`.`reference_id` = `eplan_court_cases`.`reference_id`
where `ep_cc_status` = 1
group by `eplan_court_cases`.`reference_id`)
and `is_form_submitted` = 1
and `st_code` in ('U05', 'S13', 'S01')
group by `reference_id`
order by `created_at` desc
You can use closure as the second parameter of the whereIn method.
whereIn($column, $values, $boolean = 'and', $not = false)
$return = DB::table('eplan_vacancy')
->whereIn('reference_id', function ($query) {
return $query->select('eplan_ep_details.reference_id')
->from('eplan_ep_details')
->join('eplan_court_cases', 'eplan_ep_details.reference_id', '=', 'eplan_court_cases.reference_id')
->where('ep_cc_status', 1)
->groupBy('eplan_court_cases.reference_id');
})
->where('is_form_submitted', 1)
->whereIn('st_code', ['U05', 'S13', 'S01'])
->groupBy('reference_id')
->orderBy('created_at', 'desc');
dd($return->toSql());
Result
select * from `eplan_vacancy` where `reference_id` in
(
select `eplan_ep_details`.`reference_id`
from `eplan_ep_details`
inner join `eplan_court_cases` on `eplan_ep_details`.`reference_id` = `eplan_court_cases`.`reference_id`
where `ep_cc_status` = ?
group by `eplan_court_cases`.`reference_id`
)
and `is_form_submitted` = ?
and `st_code` in (?, ?, ?)
group by `reference_id`
order by `created_at` desc
Here is a full eloqent query that you can use to generate above query, Here i used Models that you need to change according to your model name.
EplanVacnacy: Model for table "eplan_vacancy"
$result = EplanVacnacy::whereIN('reference_id',function($q){
$q->from('eplan_ep_details')
->select('eplan_ep_details.reference_id')
->innerJoin('eplan_court_cases','eplan_ep_details.reference_id','=','eplan_court_cases.reference_id')
->where('eplan_ep_details.ep_cc_status',1)
->groupBy('eplan_court_cases.reference_id')
->get();
return $q;
})
->where('is_form_submitted',1)
->whereIN('st_code',['U05', 'S13', 'S01'])
->groupBy('reference_id')
->orderBy('created_at','desc')
->get();
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();
My current query is
select * from `users` where `group_id` = 1 and ((select count(*) from `works` inner join `user_work` on `works`.`id` = `user_work`.`work_id` where `user_work`.`user_id` = `users`.`id` and `work_duration_id` >= 3) >= 1)
For this query I have written following eloquent method in laravel 4.2 and it is working fine
$u = User::where('group_id', '=', 1);
$u = $u->where(function($m) use($minWorkDuration,$searchCriteria){
$m = $m->whereHas('work', function($q) use($minWorkDuration){
$q->where('work_duration_id', '>=', $minWorkDuration );
});
});
But I want to change in my query little bit and this is
select * from `users` where `group_id` = 1 and ((select count(*) from `works` inner join `user_work` on `works`.`id` = `user_work`.`work_id` where `user_work`.`user_id` = `users`.`id` and (SELECT SUM(`work_duration_id`) from `works` group by `user_id`) >= 3) >= 1)
If I want to write this query then what will be in eloquent method. If anybody is there please suggest me how to write this query in eloquent method in laravel 4.2.
Thanks in advance.
I have a problem converting my MySQL query to codeigniter syntax.
This is my MySQL query.
Select id, name, code, status, question_count, session
from s3r_set
left join
(Select set_id, count(id) as question_count
from s3r_question group by set_id) question
on question.set_id = id
left join
(SELECT session_id as session, set_id
from s3r_session) s3rsession
on s3rsession.set_id = id
order by id
This is what I've got so far in CI:
$this->db->select('id, name, code, status, question_count, session');
$this->db->from('s3r_set');
$this->db->join('s3r_question', '(Select set_id, count(id) as question_count
from s3r_question group by set_id) question
on question.set_id = id', 'left');
$this->db->join('s3r_session', '(SELECT session_id as session, set_id
from s3r_session) s3rsession
on s3rsession.set_id = id', 'left');
$this->db->order_by('id', "desc");
$q = $this->db->get();
if($q->num_rows() > 0)
{
return $q->result();
}
else
{
return false;
}
Thanks for help in advance.
Well for one you are doing the join wrong:
$this->db->join('s3r_question', '(Select set_id, count(id) as question_count
from s3r_question group by set_id) question
on question.set_id = id', 'left');
Should be:
$this->db->join('(Select set_id, count(id) as question_count
from s3r_question group by set_id) question', 'question.set_id = id');
Refer to formatting here:
http://ellislab.com/codeigniter/user-guide/database/active_record.html#join
The ...join(FROM_TABLE, ON WHAT VALUE TO JOIN ON, OPTIONAL > WHAT TYPE OF JOIN, LEFT/RIGHT/ETC;)