OrderBy is not working while applying GroupBy Laravel - php

I am using following query to retrieve the user feeds but ordering latest update is not working when we applying order created_at time by desc
Here i have given SQL query. Kindly suggest me solution to solve my problem
select `users`.`id` as `uid`, `updates`.`post_id`, `updates`.`id` as `upid`, `friends`.`id` as `fid`, `updates`.`user_id`, `updates`.`privacy`, `updates`.`updated_at`, `updates`.`created_at`, `friends`.`first_user_id`, `friends`.`second_user_id`, `friends`.`friend_status`, `updates`.`update_type` from `updates`
inner join `users` on `updates`.`user_id` = `users`.`id`
inner join `friends` on
CASE
WHEN friends.first_user_id = 1
THEN friends.second_user_id = updates.user_id
WHEN friends.second_user_id= 1
THEN friends.first_user_id = updates.user_id
END
where `friends`.`friend_status` > 0
and `updates`.`privacy` in (1,2)
and `updates`.`user_id` != 1 and
`updates`.`deleted_at` is null
group by `updates`.`post_id`
order by `updates`.`created_at` desc
Laravel Code
Update::select(
'users.id as uid', 'posts.id as pid', 'updates.post_id', 'updates.id as upid',
'friends.id as fid', 'updates.user_id', 'updates.privacy', 'updates.updated_at', 'updates.created_at', 'posts.deleted_at', 'friends.first_user_id',
'friends.second_user_id', 'friends.friend_status', 'updates.update_type', 'posts.wall_user_id'
)->join('users', 'updates.user_id', '=', 'users.id')
->join('posts', 'posts.id', '=', 'updates.post_id')
->join('friends', function($join) use ($userId){
$join->on(DB::raw('CASE
WHEN friends.first_user_id = '.$userId.'
THEN friends.second_user_id = updates.user_id
WHEN friends.second_user_id= '.$userId.'
THEN friends.first_user_id = updates.user_id
END'
), DB::raw(''), DB::raw(''));
})->where('friends.friend_status', '>', 0)
->whereIn('updates.privacy', [1,2])
->where('updates.user_id', '!=', Auth::user()->id)
->groupBy('updates.post_id')
->orderBy('updates.created_at', 'DESC')
->get();

select * from(select `users`.`id` as `uid`, `updates`.`post_id`, `updates`.`id` as `upid`, `friends`.`id` as `fid`, `updates`.`user_id`, `updates`.`privacy`, `updates`.`updated_at`, `updates`.`created_at`, `friends`.`first_user_id`, `friends`.`second_user_id`, `friends`.`friend_status`, `updates`.`update_type` from `updates`
inner join `users` on `updates`.`user_id` = `users`.`id`
inner join `friends` on
CASE
WHEN friends.first_user_id = 1
THEN friends.second_user_id = updates.user_id
WHEN friends.second_user_id= 1
THEN friends.first_user_id = updates.user_id
END
where `friends`.`friend_status` > 0
and `updates`.`privacy` in (1,2)
and `updates`.`user_id` != 1 and
`updates`.`deleted_at` is null order by `updates`.`created_at` desc) as tmp_table
group by `updates`.`post_id`

Related

Return only values that have all the necesary relations [duplicate]

In Laravel 4.2, I am trying to achieve a query that returns all users, that have all of certain activities. As of now, I have a query that returns all users that have one of many activities:
//$selectedActivities being an array
$userByActivities = User::with('activities')
->whereHas('activities', function($query) use($selectedActivities){
$query->whereIn('id', $selectedActivities);
})->get();
To be more clear: given activities a,b,c. I am looking for all users that have activity a AND b AND c. My query returns all users that have activity a OR b OR c.
Thank you for your help.
EDIT:
The solution offered by lukasgeiter results in following query:
select * from `users` where
(select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '7') >= 1
and (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '3') >= 1
and (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '1') >= 1
and (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '2') >= 1
Whereas the solution offered by Jarek Tkaczyk:
$userByActivities = User::with('activities')
->whereHas('activities', function($query) use($selectedActivities) {
$query->selectRaw('count(distinct id)')->whereIn('id', $selectedActivities);
}, '=', count($selectedActivities))->get();
for a similar request, results in following query:
select * from `users` where (select count(distinct id) from `activities`
inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id`
where `activity_user`.`user_id` = `users`.`id` and `id` in ('7', '3', '1', '2')) = 4
You'll have to add multiple whereHas for that:
$query = User::with('activities');
foreach($selectedActivities as $activityId){
$query->whereHas('activities', function($q) use ($activityId){
$q->where('id', $activityId);
});
}
$userByActivities = $query->get();
If you are getting Cardinality violation: 1241 Operand should contain 2 column(s) the problem is the nested selectCount adds to the normal select count(*) instead of overriding the existing select, so changing to $query->distinct()->whereIn('id', $selectedActivities); did the trick for me, or changing to $query->select(DB::raw(count(distinct id)))

How to get data in laravel joins?

I am using join in laravel with mutiples and different conditions but I have a problem the quantity and the date column is always null but when I see in the database the column is not null it has some value it is only null when I am using join.
$contact_packages = Contact::where('contacts.id','!=',1)
->leftJoin('transactions as t','t.id','=','contacts.id')
->leftJoin('transaction_sell_lines as tsl','tsl.transaction_id','=','t.id')
->join('customer_package as cp','contacts.id','=','cp.contact_id')
->join('package as p','cp.package_id','=','p.id')
->join('customer_package_service as cps','cps.customer_package_id','=','cp.id')
->leftJoin('categories as c','p.category_id','=','c.id')
->leftJoin('categories as sc','p.sub_category_id','=','sc.id')
// ->where('cps.customer_package_id','cp.id')
->select([
'contacts.id as cid',
'contacts.name as cname',
'p.id as pid',
'p.name as pname',
DB::raw('TRIM(tsl.quantity)+0 as pqty'),
// 'tsl.quantity as pqty',
DB::raw('count(cps.product_id) as services'),
DB::raw('COUNT(CASE WHEN cps.status = 0 THEN cps.product_id END) as pending'),
DB::raw('COUNT(CASE WHEN cps.status = 1 THEN cps.product_id END) as redeemed'),
't.created_at as date',
'c.name as pc',
'sc.name as psc',
'p.expire_days as ped',
'cps.customer_package_id as cpid'
])
->groupBy('cpid')
->get();
select `contacts`.`id` as `cid`, `contacts`.`name` as `cname`,
`p`.`id` as `pid`, `p`.`name` as `pname`,
TRIM(tsl.quantity)+0 as pqty, count(cps.product_id) as services,
COUNT(CASE WHEN cps.status = 0 THEN cps.product_id END) as pending,
COUNT(CASE WHEN cps.status = 1 THEN cps.product_id END) as redeemed,
`t`.`created_at` as `date`, `c`.`name` as `pc`,
`sc`.`name` as `psc`, `p`.`expire_days` as `ped`,
`cps`.`customer_package_id` as `cpid` from `contacts`
left join `transactions` as `t` on `t`.`id` = `contacts`.`id`
left join `transaction_sell_lines` as `tsl` on `tsl`.`transaction_id` = `t`.`id`
inner join `customer_package` as `cp` on `contacts`.`id` = `cp`.`contact_id`
inner join `package` as `p` on `cp`.`package_id` = `p`.`id`
inner join `customer_package_service` as `cps` on `cps`.`customer_package_id` = `cp`.`id`
left join `categories` as `c` on `p`.`category_id` = `c`.`id`
left join `categories` as `sc` on `p`.`sub_category_id` = `sc`.`id`
where `contacts`.`id` != ?
and `contacts`.`deleted_at` is null
group by `cpid`
I just had to put the foreign name in first join I put the primary key which is wrong.
$contact_packages = Contact::where('contacts.id','!=',1)
->leftJoin('transactions as t','t.contact_id','=','contacts.id')
->leftJoin('transaction_sell_lines as tsl','tsl.transaction_id','=','t.id')
->join('customer_package as cp','contacts.id','=','cp.contact_id')
->join('package as p','cp.package_id','=','p.id')
->join('customer_package_service as cps','cps.customer_package_id','=','cp.id')
->leftJoin('categories as c','p.category_id','=','c.id')
->leftJoin('categories as sc','p.sub_category_id','=','sc.id')
// ->where('cps.customer_package_id','cp.id')
->select([
'contacts.id as cid',
'contacts.name as cname',
'p.id as pid',
'p.name as pname',
DB::raw('TRIM(tsl.quantity)+0 as pqty'),
// 'tsl.quantity as pqty',
DB::raw('count(cps.product_id) as services'),
DB::raw('COUNT(CASE WHEN cps.status = 0 THEN cps.product_id END) as pending'),
DB::raw('COUNT(CASE WHEN cps.status = 1 THEN cps.product_id END) as redeemed'),
't.created_at as date',
'c.name as pc',
'sc.name as psc',
'p.expire_days as ped',
'cps.customer_package_id as cpid'
])
->groupBy('cpid')
->get();

Subqueries in Laravel/Eloquent not working

I am currently working on a Lumen based application and I am stuck on an Eloquent/Laravel query. What I am currently working on is this:
$min = $filter['min_spending']*100;
$query = User::isCustomer()
->with("interests")
->leftJoin("points_history", "points_history.user_id", "=", "users.id")
->leftJoin("collections", "collections.user_id", "=", "users.id")
->select("users.*",
DB::raw("(SELECT SUM(amount) FROM points_history
WHERE points_history.user_id = users.id
AND points_history.confirmed = true ) as total_points"),
DB::raw("(SELECT SUM(price) FROM collections
WHERE paid_at IS NOT NULL
AND refunded_at IS NULL
AND collections.user_id = users.id) as total_purchase"),
DB::raw("(SELECT SUM(collections.price)) as current_purchase"))
->where("total_purchase", ">=", $min);
// other relevant code here
$query->groupBy('users.id')->orderBy('users.created_at', 'desc');
However, when I try to get the result, I get this error:
{"error":"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'total_purchase >=' in 'where clause' (SQL: select count(*) as aggregate from `users` left join `points_history` on `points_history`.`user_id` = `users`.`id` left join `collections` on `collections`.`user_id` = `users`.`id` where `users`.`deleted_at` is null and `role` = 2 and `total_purchase >=` = 200000 group by `users`.`id`)"}
The subqueries did not seem to register which is causing the problem (?) My desired SQL Statement is this:
SELECT users . *,
(SELECT
SUM(amount)
FROM
points_history
WHERE
points_history.user_id = users.id
AND points_history.confirmed = true) AS total_points, (SELECT
SUM(price)
FROM
collections
WHERE
paid_at IS NOT NULL
AND refunded_at IS NULL
AND collections.user_id = users.id) AS total_purchase, SUM(collections.price) AS current_purchase
from
users
left join
points_history ON points_history.user_id = users.id
left join
collections ON collections.user_id = users.id
where
users.deleted_at is null AND (SELECT
SUM(price)
FROM
collections
WHERE
paid_at IS NOT NULL
AND refunded_at IS NULL
AND collections.user_id = users.id) >= 200000
GROUP BY users.id
where 200000 is $min. Could anyone help me pinpoint what the problem is in my query so I can figure out how to fix it?
You should try this:
$min = $filter['min_spending']*100;
$query = User::isCustomer()
->with("interests")
->leftJoin("points_history", "points_history.user_id", "=", "users.id")
->leftJoin("collections", "collections.user_id", "=", "users.id")
->select("users.*",
DB::raw("(SELECT SUM(amount) FROM points_history
WHERE points_history.user_id = users.id
AND points_history.confirmed = true ) as total_points"),
DB::raw("(SELECT SUM(price) FROM collections
WHERE paid_at IS NOT NULL
AND refunded_at IS NULL
AND collections.user_id = users.id) as total_purchase"),
DB::raw("(SELECT SUM(collections.price)) as current_purchase"))
->where("total_purchase", '>=', $min);
// other relevant code here
$query->groupBy('users.id')->orderBy('users.created_at', 'desc');
->where("total_purchase",">=", $min);
In the quick view, you did not put "," in the last line
FIXED:
Apparently, SELECT does not take multiple args but it accepts an array
->select(["users.*",
DB::raw("(SELECT SUM(amount) FROM points_history
WHERE points_history.user_id = users.id
AND points_history.confirmed = true ) as total_points"),
DB::raw("(SELECT SUM(price) FROM collections
WHERE paid_at IS NOT NULL
AND refunded_at IS NULL
AND collections.user_id = users.id) as total_purchase"),
DB::raw("(SELECT SUM(collections.price)) as current_purchase")]
Also ended up changing the WHERE clause to
$query->whereRaw(DB::raw("(SELECT SUM(amount) FROM points_history
WHERE points_history.user_id = users.id
AND points_history.confirmed = true ) <= " . $max));
with a dot instead of a comma to concatenate to the query

How can i convert this SQL to Laravel eloquent?

I have the following SQL
SELECT C.CUOCODE, C.NAME, COUNT(*) TOTAL_PAYMENT, SUM(P.AMOUNT) TOTAL_AMOUNT
FROM TAX_PAYMENT P
INNER JOIN TAX_CHECKPOINT C ON C.CUOCODE = REGEXP_SUBSTR(P.INVOICEID, 'R....')
WHERE DELETED = 0 AND TO_CHAR(TXTIME,'YYYY-MM-DD') = '2018-04-24'
GROUP BY C.CUOCODE, C.NAME
ORDER BY TOTAL_AMOUNT DESC;
How can i convert to laravel eloquent, i have "Payment" model (table TAX_PAYMENT) with "paymentid" as primary key.
DB::table('TAX_PAYMENT as P')
->select([
'C.CUOCODE',
'C.NAME',
DB::raw('COUNT(*) AS TOTAL_PAYMENT'),
DB::raw('SUM(P.AMOUNT) AS TOTAL_AMOUNT'),
])->Join('TAX_CHECKPOINT C', 'C.CUOCODE', '=', DB::raw('REGEXP_SUBSTR(P.INVOICEID,'R....')'))
->where('DELETED', 0)
->where(DB::raw("TO_CHAR(TXTIME,'YYYY-MM-DD')"), '2018-04-24')
->groupBy('C.CUOCODE')
->groupBy('C.NAME')
->orderBy('TOTAL_AMOUNT', 'desc')
->toSql();
output
SELECT
`C`.`CUOCODE`,
`C`.`NAME`,
COUNT(*) AS TOTAL_PAYMENT,
SUM(P.AMOUNT) AS TOTAL_AMOUNT
FROM
`TAX_PAYMENT` AS `P`
INNER JOIN `TAX_CHECKPOINT C` ON `C`.`CUOCODE` = REGEXP_SUBSTR (P.INVOICEID,"R....")
WHERE
`DELETED` = ?
AND TO_CHAR (TXTIME, 'YYYY-MM-DD') = ?
GROUP BY
`C`.`CUOCODE`,
`C`.`NAME`
ORDER BY
`TOTAL_AMOUNT` DESC
A quick and dirty way would be to use Eloquents select raw like:
$result = DB::select( DB::raw("SELECT C.CUOCODE, C.NAME, COUNT(*)
TOTAL_PAYMENT, SUM(P.AMOUNT) TOTAL_AMOUNT FROM TAX_PAYMENT INNER JOIN
TAX_CHECKPOINT C ON C.CUOCODE
= REGEXP_SUBSTR(P.INVOICEID, 'R....') WHERE DELETED = 0 AND
TO_CHAR(TXTIME,'YYYY-MM-DD') = '2018-04-24' GROUP BY C.CUOCODE,
C.NAME ORDER BY TOTAL_AMOUNT DESC"));

Get all objects from database that are not in a relationship yet

I have the following query and it's doing it's job fine:
SELECT exams.id, exams.date FROM exams
WHERE exams.modul_id = (SELECT questions.modul_id FROM questions where questions.id = 5)
AND NOT EXISTS (
SELECT * FROM exam_question, questions
WHERE questions.id = 5
AND questions.id = exam_question.question_id
AND exam_question.exam_id = exams.id
)
It returns me all exams that belong to the same model as exam but not connteced to exam yet.
I want to use this query in Laravel but I always get an empty result back (it shouldn't be empty)
DB::table('exams')
->select(['id', 'date'])
->whereRaw('modul_id = '.$question->modul_id)
->whereNotExists(function ($query) use ($question) {
$query->select(DB::raw(1))
->from('questions as q')
->join('exam_question as eq', 'q.id', '=', 'eq.question_id')
->join('exams as e', 'eq.exam_id', '=', 'e.id')
->whereRaw('q.id = '.$question->id);
})
->get();
The output of the laravel expression is:
select `id`, `date` from `exams` where modul_id = 1 and not exists (select 1 from `questions` as `q` inner join `exam_question` as `eq` on `q`.`id` = `eq`.`question_id` inner join `exams` as `e` on `eq`.`exam_id` = `e`.`id` where q.id = 5)
I see problem in your sql query dump in section and not exists (... you select starts with select 1 from it will always select number 1 from your table according to selected rows count
select `id`, `date` from `exams`
where modul_id = 1
and not exists (
select 1 from `questions` as `q`
inner join `exam_question` as `eq` on `q`.`id` = `eq`.`question_id`
inner join `exams` as `e` on `eq`.`exam_id` = `e`.`id` where q.id = 5)
You have to use in query builder instead $query->select(DB::raw(1)) ... -> $query->select('*') ...
DB::table('exams')
->select(['id', 'date'])
->whereRaw('modul_id = '.$question->modul_id)
->whereNotExists(function ($query) use ($question) {
$query->select('*')
->from('questions as q')
->join('exam_question as eq', 'q.id', '=', 'eq.question_id')
->join('exams as e', 'eq.exam_id', '=', 'e.id')
->whereRaw('q.id = '.$question->id);
})
->get();
If the rest logic which you used to create your query is correct it will start to work

Categories