So I have table prices with structure:
+----+--------+
| id | reward |
+----+--------+
| 1 | 721 |
+----+--------+
| 2 | 54 |
+----+--------+
| 3 | 99 |
+----+--------+
and I'm using this method to sum all rewards:
'withdrawals' => \App\Tradeoffer::where('type', 'withdraw')
->where('completed', 1)
->where('declined', 0)
->where('timeout', 0)
->where('created_at', '>', (time() - $hours))
->sum('reward')
and the response is: 7215499 instead of sum of all entries. Why is that? How to deal with it?
I think you can do it like,
$totalReward = \App\Tradeoffer::selectRaw('SUM(reward) as total')
->where('type', 'withdraw')
->where('completed', 1)
->where('declined', 0)
->where('timeout', 0)
->where('created_at', '>', (time() - $hours))
->first();
$totalReward->total;
Instead of use the model I use a Query Builder and it works (with my database)
DB::table('Tradeoffer') // Here is the name of the table
->where('type', 'withdraw')
->where('completed', 1)
->where('declined', 0)
->where('timeout', 0)
->where('created_at', '>', (time() - $hours))
->sum('reward');
Try it!
What you should do is making sure your reward column in prices table in database is number (integer/float) and not varchar
Related
In my products table, I have 2 columns: price and discounted_price in which discounted_price is null most of the time unless there is a promotion for that product:
+----+--------------------+-------+------------------+
| id | name | price | discounted_price |
+----+--------------------+-------+------------------+
| 1 | test 1 | 79.00 | null |
| 2 | test 2 | 50.00 | 45.00 |
+----+--------------------+-------+------------------+
The product with id of 2 is now on promotion and has discounted_price.
Now I want to query products to get products cheaper than 50 but in my query I need to check if discounted_price is null then look into price, otherwise look into discounted_price. What Google said is using:
$products = Product::where('coalesce(price, discounted_price) <= 50);
But it's not working :(
Alternative, you can use sub query, like this :
$q = 50;
$product = Product::where(function($query) use($q) {
$query->where('discounted_price', '<=', $q)
->orWhere('price', '<=', $q)
})
->get();
you can use whereRaw
instead of where or where(DB::raw('coalesce(price, discounted_price') <= 50))
also be carful to close your where by ' character
i recommend using where with clouser like this:
$products = Product::where(function ($query)
{
$query->where('discounted_price',null)->where('price','<=',50);
})->orWhere('discounted_price','<=',50)->get();
I've a following attendance table:
id | grade_id | subject_id | date | students
1 | 2 | 6 | 2020-05-05 | [3,6,8,11,17,21,20,19]
I want to fetch all rows with name of all students from array of Ids.
What I've tried is:
$result[] = Attendance::where('date', '=', $day)
->with('grades', 'subjects')
->join('students', function($join) {
$join->on('students.id', '=', 'attendances.id')
->where('students.id', '=', 'attendances.students');
})->get();
But couldn't get result. Please help me!
It is not a proper table structure.Will be better if you make another table like
id | attendance_id | student_id
1 | 1 | 3
1 | 1 | 6
And make its relation in model with attendance and student table.This way table will be normalized and will be easy to handle relationship.
I have two tables as shown below. I am using Laravel DB method to join this table. But I am not getting how can I get the count of marks of students as per failed or passed. 0-failed 1-passed.
Expected result:
1. Student Name
2. Student Id,
3. Count of failed based on student Id as count_failed
4. Total Marks based on student Id as total_marks
table students
`+----+-----------+
| id | name |
+----+-----------+
| 1 | John Doe |
| 2 | Mark P |
| 3 | Pen Henry |
+----+-----------+`
table students_marks:
+----+------------+-------+-----------+
| id | student_id | marks |is_failed |
+----+------------+-------+-----------+
| 1 | 1 | 55 | 0 |
| 2 | 2 | 44 | 1 |
| 3 | 1 | 11 | 1 |
| 4 | 2 | 10 | 0 |
| 5 | 2 | 11 | 1 |
| 6 | 2 | 20 | 0 |
+----+------------+-------+-----------+
Below is query which I used:
$users = DB::table('users')
->join('contacts', 'students.id', '=', 'students_marks.user_id')
->select('student.*')
->get();
I am unable to get how can we use count() with conditional SQL in select() of laravel?
Use conditional aggregation:
$users = DB::table('students s')
->leftJoin('students_mark sm', 's.id', '=', 'sm.user_id')
->groupBy('sm.id')
->select(DB::raw('s.id, s.name, SUM(sm.is_failed) AS num_failed, COUNT(sm.user_id) AS total_cnt'))
->get();
This corresponds to the following raw MySQL query:
SELECT
s.id,
s.name,
SUM(sm.is_failed) AS num_failed,
COUNT(sm.user_id) AS total_cnt
FROM students s
LEFT JOIN students_marks sm
ON s.id = sm.user_id
GROUP BY
s.id;
Note: It is acceptable in ANSI SQL to select the name field in the above GROUP BY query assuming that student#id is the primary key column for that table. If the above query gives an ONLY_FULL_GROUP_BY error, then simply add s.name to the GROUP BY clause.
$users = DB::table('users')
->join('contacts', 'students.id', '=', 'students_marks.user_id')
->select('student.*', DB::raw("count(students_marks.is_failed) as count")))
->where('status', '=', 0)
->get();
Try this.
If this is not clear or doesn't work refer this
Try this code snippet
$table = DB::table('students_marks');
$table = $table->select(
\DB::raw('SUM(if(is_failed = '0', 1, 0)) AS failed'),
\DB::raw('SUM(if(is_failed = '1', 1, 0)) AS passed'),
\DB::raw('SUM(marks) AS total'));
$table = $table->Join('students', 'students.id', '=', 'students_marks.student_id');
$table = $table->get();
Try this
$users = DB::table('students s')
->leftJoin('students_mark sm', 's.id', '=', 'sm.student_id')
->groupBy('s.id','s.name')
->selectRaw("s.id,s.name,SUM(sm.is_failed) AS count_failed,SUM(sm.marks) as total_marks")
->get();
I have the table like that
|----|--------|------------|--------|
| id | UserID | ExpDate | isUsed |
|----|--------|------------|--------|
| 1 | 1265 | 2019-09-08 | 0 |
|----|--------|------------|--------|
| 2 | 1265 | 2019-08-28 | 0 |
|----|--------|------------|--------|
| 3 | 1265 | null | 0 |
|----|--------|------------|--------|
| 4 | 1265 | null | 1 |
|----|--------|------------|--------|
| 5 | 1582 | 2019-09-07 | 0 |
|----|--------|------------|--------|
. . . .
. . . .
. . . .
I want to select rows that User = 1265 and isUsed = 0 and ( ExpDate > 2019-09-05 or ExpDate = null)
How to make these selection using laravel eloquent?
I've tried below but it selects all ExpDate is bigger than 2019-09-05 rows on table. Not filtered by UserID
Hak::whereNull('ExpDate')
->orWhere('ExpDate', '>', '2019-09-05')
->where('UserID', 23)
->get()
You can try with below.
Hak::where(function($query){
$query->whereNull('ExpDate')->orWhere('ExpDate', '>', '2019-09-05');
})->where(['User'=>1265, 'isUsed' => 0])->get();
You can use sub query to achieve this i haven't tested it but you can give it a try.
Hak::where('UserID', 23)->where('isUsed', 0)->where(function ($q){
$q->whereNull('ExpDate')
->orWhere('ExpDate', '>', '2019-09-05');
})->get();
i think i would write the SQL as followes as OR optimizes badly in MySQL..
Pretty sure fully supported Parallel Query Execution will change that in the future.
As they are working on this feature if you want you can read MySQL 8.0.14: A Road to Parallel Query Execution is Wide Open!
The SQL result might be wrong as you didn't provide example data and expected result see Why should I provide a Minimal Reproducible Example for a very simple SQL query? for providing those.
Query
SELECT
*
FROM
your_table
WHERE
UserID = 23
AND
isUsed = 0
AND
ExpDate > '2019-09-05'
UNION ALL
SELECT
*
FROM
your_table
WHERE
UserID = 23
AND
isUsed = 0
AND
ExpDate IS NULL
Laravel code
To warn you i didn't program in Laravel for some time now so this code might be wrong.
<?php
$first = DB::table('your_table')
->select('your_table.*')
->where('UserID ', '=', 1)
->andWhere('isUsed ', '=', 0)
->andWhere('ExpDate ', '>', '2019-09-05')
;
$second = DB::table('your_table')
->select('your_table.*')
->where('UserID ', '=', 1)
->andWhere('isUsed', '=', 0)
->whereNull('ExpDate')
->union($first)
->get();
?>
It can be confusing coming from SQL, but you'll need two orWhere in Eloquent to achieve this. So basically:
Hak::orWhereNull('ExpDate')
->orWhere('ExpDate', '>', '2019-09-05')
->where('UserID', 23)
->get()
EDIT: Haven't tested it though, but you might need a subquery to filter the userId as well.
I want to get all the purchases and their sums and also I don't want to add the amount if payments.deleted_at is not null.
Here are the tables
purchases
id | name
1 | Gamerzone Book
2 | Recipe Book
3 | EngineX Book
payments
id | purchase_id | amount | deleted_at
1 1 100 2015-06-12 11:00:00
2 2 50 NULL
2 2 10 NULL
Code
$query = DB::table('purchases')
->select(['purchases.*',
DB::raw("IFNULL(sum(payments.amount),0) as total")
])
->leftJoin('payments','payments.purchase_id','=','purchases.id')
->whereNull('payments.deleted_at')
->groupBy('purchases.id')->get();
When I run the code below the 1st result is not included.
Result
id | name | total
2 | Recipe Book 60
3 | EngineX Book 0
I know why It is not included but the problem is if I remove whereNull('payments.deleted_at') that particular row in payments
will also add to the sum.How should I solve this ??
Expected Result
id | name | total
1 | Gamerzone Book 0
2 | Recipe Book 60
3 | EngineX Book 0
In this case your join condition should looks like this:
ON (payments.booking_id = purchases.id AND payments.deleted_at IS NOT NULL)
And it is not about WHERE (according to your SELECT).
You should use join-closure like this:
$query = DB::table('purchases')
->select(['purchases.*', DB::raw("IFNULL(sum(payments.amount),0) as total")])
->leftJoin('payments', function($join) {
$join->on('payments.booking_id', '=', 'purchases.id');
$join->on('payments.deleted_at', 'IS', DB::raw('NOT NULL'));
})
->groupBy('purchases.id')->get();
Just replace
->leftJoin('payments','payments.booking_id','=','purchases.id')
with
->leftJoin('payments', function($join) {
$join->on('payments.booking_id', '=', 'purchases.id');
$join->on('payments.deleted_at', 'IS', DB::raw('NOT NULL'));
})
and remove this:
->whereNull('payments.deleted_at')
it should help.