Laravel ORM query builder - php

I have the following interrogation that I want to translate into Laravel's Query Builder:
SELECT t.name, t.description, u.first_name as assignee_fname, u.last_name as assignee_lname,
us.first_name as reporter_fname, us.last_name as reporter_lname
FROM `tasks` AS t
LEFT JOIN `users` AS u
ON (t.asignee_id = u.id)
LEFT JOIN `users` AS us
ON (t.reporter_id = us.id);
Do you have any idea how can I do that?
Thank you

DB::table('tasks')->select('tasks.name', 'users.first_name AS assignee_fname', ...) //and the rest of your column
->leftJoin('users', 'taks.asignee_id', '=', 'users.id')
->leftJoin('users', 'tasks.reporter_id', '=', 'users.id')

Related

Converting complex SQL select to Laravel Eloquent

I am new to Laravel and trying to support an existing application that is in Laravel 5. I am trying to convert the following SQL to eloquent structure
SELECT s.id,
CONCAT(u.first_name, ' ', u.last_name) AS user_name,
u.avatar_location AS user_img,
s.employee_photo,
d.name AS department,
seg.name AS segment,
s.survey_title,
s.before_action,
s.before_picture,
s.action,
s.action_date,
s.after_action,
s.after_picture,
s.nominated,
s.awarded,
s.created_at,
s.updated_at,
(SELECT COUNT(1) FROM likes l WHERE l.survey_id = s.id) AS likes,
(SELECT COUNT(1) FROM likes l WHERE l.survey_id = s.id AND l.user_id = 5) AS UserLikes,
(SELECT COUNT(1) FROM comments c WHERE c.survey_id = s.id ) AS comments
FROM surveys s
JOIN departments d
ON s.department = d.id
JOIN segments seg
ON s.segment_id = seg.id
JOIN users u
ON s.user_id = u.id
WHERE s.status = 'Approved'
ORDER BY s.action_date DESC
LIMIT 20 OFFSET 20
I know enough Laravel to know that my basic start would probably be
$surveys = DB::table('surveys')
->join('departments', 'surveys.department', '=', 'departments.id')
->join('segments', 'surveys.segment_id', '=', 'segments.id')
->join('users', 'surveys.user_id', '=', 'users.id')
->where('surveys.status', 'Approved')
->orderBy('surveys.action_date')
->skip(20)-take(20)
->select(...)->get();
However, I am not sure how to do the subqueries. Looking for any suggestions.
Thanks!
For select statements, you can use DB::raw().
$surveys = DB::table('surveys')
->join('departments', 'surveys.department', '=', 'departments.id')
->join('segments', 'surveys.segment_id', '=', 'segments.id')
->join('users', 'surveys.user_id', '=', 'users.id')
->where('surveys.status', 'Approved')
->orderBy('surveys.action_date')
->skip(20)-take(20)
->select([DB::raw('(SELECT COUNT(1) FROM likes l WHERE l.survey_id = s.id) AS likes'),
...
])
->get();
Similarly, select statements would go under the select array. Just so to be clear, the result will be a collection.

How to convert a specific PostgreSQL query to laravel query builder

Im trying to convert a postgresql query to the laravel query builder style.
I have almost no experience with the laravel query builder. I dont want to use the DB raw.
SELECT ca1.component, ca1.previousfeeder, COUNT(ca1.previousfeeder)
FROM mydbcarrdata_10.carrier ca1
WHERE ca1.component IN (
SELECT e.articlename
FROM mydbcarrdata_10.carrier ca
JOIN mydbcompdata_10.component co
ON ca.component = co.name
JOIN mydbmanldata_10.entry e
ON e.articlename = co.name
JOIN mydbmanldata_10.header h
ON h.id = e.headerid
JOIN mydbmanldata_10.mandata m
ON h.layoutid = m.id
JOIN mydblytldata_10.layout l
ON m.layout = l.name
WHERE l.name = 'M2077F_bottom'
GROUP BY e.articlename
)
GROUP BY ca1.component, ca1.previousfeeder
ORDER BY ca1.component asc
Ive found the corresponding query using the query builder:
DB::table('mydbcarrdata_10.carrier')->select(DB::raw('component, previousfeeder, count(previousfeeder)'))
->whereIn('component', DB::table('mydbcarrdata_10.carrier')->select('articlename')
->join('mydbcompdata_10.component', 'component.name', '=', 'carrier.component')
->join('mydbmanldata_10.entry', 'component.name', '=', 'entry.articlename')
->join('mydbmanldata_10.header', 'entry.headerid', '=', 'header.id')
->join('mydbmanldata_10.mandata', 'mandata.id', '=', 'header.layoutid')
->join('mydblytldata_10.layout', 'layout.name', '=', 'mandata.layout')
->where('layout.name', '=', 'M2077F_bottom')
->groupBy('entry.articlename')
->pluck('articlename')
)
->groupBy('component', 'previousfeeder')
->orderBy('component', 'asc')
->get();

GROUP_CONCAT gives incorrect values

I have 3 tables: Users, Properties, Units
User table:
user_id user_name
Properties table
pty_id pty_name user pty_status
Units Table
unit_id unit_name pty_id unit_status
i want to show user details , number of properties and units and their details.
Here is my query:
DB::statement('SET SESSION group_concat_max_len = 10485760');
$ar = DB::table('users as u')
->leftjoin('properties as p', function($join) {
$join->on('p.user_id', '=', 'u.user_id')->where('p.pty_status', '!=' ,0 );
})
->leftJoin(
DB::raw("
(select COALESCE(count(unit_id),0) AS cntunits, pty_id as temp_pty
from property_units as pu3
left join properties as p2 on pu3.unit_pty_id = p2.pty_id
where pu3.unit_status!=0
group by p2.pty_id) as temp"), 'p.pty_id', '=', 'temp.temp_pty')
->select(
DB::raw("group_concat(DISTINCT CONCAT(ej_p.pty_id,'|',ej_p.pty_name,'|',cntunits)) as pty_details"),
DB::raw("group_concat(DISTINCT CONCAT(ej_p.pty_id,'|',ej_p.pty_name)) as pty_details_copy")
)->paginate(10);
When I group_concat the unit_count, only those properties and units are concated where unit exists.
For example the above query returns the following result:
pty_details pty_details_copy
7|I2|2 7|I2, 22|tR ,51|SG APARTMENT,54_||_GA APARTMENTS,
Why properties with units (where unit count=0) are not binding? Where have I gone wrong?
EDIT
Here is the raw query:
select group_concat(DISTINCT CONCAT(p.pty_id,'|',p.pty_name,'|',cntunits)) as pty_details,
group_concat(DISTINCT CONCAT(p.pty_id,'|',p.pty_name)) as pty_details_copy
from users as u
left join properties as p on p.user_id = u.user_id and p.pty_status !=0
left join
(select COALESCE(count(unit_id),0) AS cntunits, pty_id as temp_pty
from property_units as pu3
left join properties as p2 on pu3.unit_pty_id = p2.pty_id
where pu3.unit_status!=0
group by p2.pty_id) as temp on p.pty_id = temp.temp_pty
As Solarflare suggested, i got the required result when I changed the query like this:
$ar = DB::table('users as u')
->leftjoin('properties as p', function($join) {
$join->on('p.user_id', '=', 'u.user_id')->where('p.pty_status', '!=' ,0 );
})
->leftJoin(
DB::raw("
(select COALESCE(count(unit_id),0) AS cntunits, pty_id as temp_pty
from property_units as pu3
left join properties as p2 on pu3.unit_pty_id = p2.pty_id
where pu3.unit_status!=0
group by p2.pty_id) as temp"), 'p.pty_id', '=', 'temp.temp_pty')
->select(
DB::raw("group_concat(DISTINCT CONCAT(ej_p.pty_id,'|',ej_p.pty_name,'|',coalesce(cntunits, 0))) as pty_details"))->paginate(10);
The WHERE from your first join should be part of the ON.

laravel - inner join query for three tables

I want to join department d table with department dl table and user u table. I have done this in SQL query.
SELECT distinct(dl.head),
u.user_name,
u.id
from department d
inner join department dl on d.parent_department_string_id=dl.string_id
inner join users u on dl.head=u.user_name
where d.sl_flag=1
I want to do the same in Laravel query. Is it possible to join the same table using join in Laravel?
You can try something like this.
$departmentData = DB::table('department AS d')
->innerJoin('department AS d1', function($join) {
$join->on('d.parent_department_string_id', '=', 'd1.string_id');
})
->innerJoin('users AS u', function($userJoin) {
$userJoin->on('d1.head', '=', 'u.user_name');
})
->where('d.sl_flag', '=', 1)
->select(\DB::raw('distinct(dl.head) AS head'), 'u.user_name', 'u.id')
->get();

Laravel 5.2 Advanced join with another join condition

so I'm building a query with the querybuilder where I need to count rows from a joined table that has a where condition from another table. I can't join that table in the end because it would result in the wrong rows being compared to this specific join. I thought the advanced join clausule would allow another join to be added in it's own scope but this seems to not be the case.
This is what I tried:
$profile = DB::table('users')
->select('users.username', 'users.profile_picture', 'users.screen_state',
'count(replies.id) as replies', 'count(interactions.id) as interactions',
'count(alerts.id) as alerts', 'count(user__followers.id) as followers',
'count(user__following.id) as following', 'count(following.id) as volgend')
->leftJoin('replies', function($join)
{
$join->on('users.id', '=', 'replies.user_id')
->leftJoin('alerts')
->on('replies.alert_id', '=', 'alerts.id')
->where('replies.user_id', '=', $user->id)
->where('alerts.hide', '=', 0);
})
->leftJoin('interactions', function($join)
{
$join->on('users.id', '=', 'interactions.user_id')
->leftJoin('alerts')
->on('interactions.alert_id', '=', 'alerts.id')
->where('interactions.user_id', '=', $user->id)
->where('alerts.hide', '=', 0);
})
->leftJoin('alerts', function($join)
{
$join->on('users.id', '=', 'alerts.user_id')
->where('alerts.user_id', '=', $user->id)
->where('alerts.hide', '=', 0);
})
->leftJoin('user__followers as user__following', function($join)
{
$join->on('users.id', '=', 'user__followers.user_id')
->where('user__followers.user_id', '=', $user->id)
->where('user__followers.follower_id', '=', $searchid);
})
->leftJoin('user__followers as following', function($join)
{
$join->on('users.id', '=', 'user__followers.user_id')
->where('user__followers.user_id', '=', $user->id);
})
->leftJoin('user__followers', function($join)
{
$join->on('users.id', '=', 'user__followers.user_id')
->where('user__followers.follower_id', '=', $user->id);
})
->where('users.id', '=', $user->id)
->get();
I also have this query in raw sql so you can see what I'm trying to achieve:
SELECT u.username, u.profile_picture, u.screen_state,
(SELECT count(DISTINCT r.id)
FROM `reply` r
LEFT JOIN alerts a
ON r.alert_id = a.alert_content_id
WHERE r.user_id = :userid AND a.hide=0)
AS replies,
(SELECT count(DISTINCT i.id)
FROM `interactions` i
LEFT JOIN alerts a
ON i.alert_id = a.alert_content_id
WHERE i.user_id = :userid AND a.hide=0)
AS interactions,
(SELECT count(DISTINCT a.alerts)
FROM `alerts` a
WHERE a.user_id = :userid AND a.hide=0)
AS alerts,
(SELECT count(DISTINCT uf.id)
FROM `user_followers` uf
WHERE uf.user_id = :userid
AND uf.follower_id = :searchid)
AS following,
(SELECT count(DISTINCT uf.id)
FROM `user_followers` uf
WHERE uf.user_id = :userid)
AS volgend,
(SELECT count(DISTINCT uf.id)
FROM `user_followers` uf
WHERE uf.follower_id = :userid)
AS followers
FROM users u
WHERE id = :userid GROUP BY id
But this gives me an error:
Call to undefined method Illuminate\Database\Query\JoinClause::leftJoin()
So my question is how can i join a table and check for a condition in yet another table?

Categories