How to get sum of two different columns with Laravel Query Builder? - php

I'm trying to get the sum of two different columns using Laravel query builder, the plain SQL Query below works just fine, but I can't get it to work with the Laravel Query.
SELECT SUM(logins_sun + logins_mon) FROM users_stats WHERE id = 7; // returns: 1034
Here's what I have tried.
$stats = DB::table('users_stats')->where('id', '=', '7')->sum('logins_sun', '+', 'logins_mon'); // returns: 587.0
And here is my DB structure.
+----+------------+------------+
| id | logins_sun | logins_mon |
+----+------------+------------+
| 7 | 587 | 447 |
+----+------------+------------+
It was supposed to return 1034 but the Laravel Query is returning only the last value 587.0 .
How can I get it working?

You can try with the sum() method like:
DB::table('users_stats')
->where('id', '7')
->sum(\DB::raw('logins_sun + logins_mon'));

sum is an aggregate function and only takes one argument. It will sum the values of each row in a column. In your case, the query only returns one row, so the sum is just the value of that one column (the first argument passed to sum()). There may be some better way to do it, but I think you should be able to use a raw expression to return the sum of the two columns.
$stats = DB::table('users_stats')
->select(DB::raw('logins_sun + logins_mon'))
->where('id', '=', '7');

Try passing a callback to the sum() and do the addition there like:
$stats = DB::table('users_stats')->where('id', '=', '7')->sum(function ($row) {
return $row->logins_sun + $row->logins_mon;
});

You can run direct raw sql in laravel with the following way :
$sql = "SELECT SUM(logins_sun + logins_mon) FROM users_stats WHERE id = :ID";
$result = DB::select($sql,['ID'=>7]);

Related

Order by infos do not have approved or rejected yet

I have HR dashboard display all forms (The applicants form)
I want to display it order by pending forms
I wrote this code but it doesn't work
public function index(){
$pending = PersonalInfo::doesntHave('hraction')->first();
$infos = PersonalInfo::orderBy($pending, 'desc')->latest()->simplePaginate();
$rank = $infos->firstItem();
return view('HR/HrEmployee',["infos",$infos,"rank"=>$rank]);
}
And this error appeared
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.jpg","personlPhoto":"resources\/images\/$2y$10$XoxGRUQiFBZgroZfj0R5ef8LnSro...' at line 1 (SQL: select * from personal_infos` order by ... limit 16 offset 0)
To be clear for you i have tow tables (personalInfos & Hractions)
prsonalInfos:
| id | firstname | fathername | ...
Hractions:
| id | user_id | action | comment | personal_id | created_at |updated_at
your variable $pending is a whole collection, you can not pass it as is, you need a column name there instead.
$infos = PersonalInfo::orderBy('firstname', 'desc')->latest()->simplePaginate();
firstname is just an example, put the appropriate field of the table you want to order there.
So basically you don't need to use the same model 2 times, you can simply do:
$infos = PersonalInfo::doesntHave('hraction')->orderBy('firstname', 'desc')->latest()->simplePaginate();
This will return you all the data from PersonalInfo model without hraction relationship and use ordering + pagination on them in one step.
orderBy()'s first argument needs to be a field in the database.
If you want to order them from latest to most recent you can use either the id field, or created_at.
Something like this:
$infos = PersonalInfo::orderBy('id', 'desc')->latest()->simplePaginate();
$infos = PersonalInfo::orderBy('created_at', 'desc')->latest()->simplePaginate();
in the end the Eloquent model queries are being transformed into plain SQL. So if you had that in mind, it will be much simpler to build the eloquent queries.

Get the highest id from a specific where clause

I have 4 records on my guests database.
I'm trying to query to the guest that has note_display = 1 and have the highest id.
I've tried
$last_note = DB::table('guests')->where('note_display','=',1)->where('id', DB::raw("(select max(`id`) from guests)"))->first();
I got
Trying to get property of non-object
I'm a lil stuck now, any hints will be a huge helps ?
There is no need to use raw in this query. You can run a simple query like
Guest::where('note_display', 1)->orderBy('id', 'desc')->first();
And it will return the Guest with the highest ID and having note_display = 1.
The raw sql string should be something like SELECT * FROM guests WHERE note_display = 1 ORDER BY id DESC LIMIT 1 it looks you are getting only rows with note_display = 1 inside a sub-query WHERE id={the maximum id present in the table}
It select the maximum of id where the the note_display is = 0, so the try to get non-object error happened.
If you're insisting to go with raw try this!
$last_note = DB::table('guests')->where('id', DB::raw("(select max(`id`) from guests where note_display = '1')"))->first();

Laravel Eloquent where field is X or null

I have a table like this:
table
- field1: tinyint
- field2: varchar (nullable)
- datefield: timestamp (nullable)
Now I want to get all entries where field1 is 1, field2 is null and where datefield is smaller than X or null. I already tried something like this:
$query = Model::where('field1', 1)
->whereNull('field2')
->where('datefield', '<', $date)
->orWhereNull('datefield');
but thats not working. I always get every entry where datefield is null. It doesn't matter what the other fields are. I also tried to split it in 2 queries: First get every row where datefield is smaller than X or null and then (based on it) get every field where field1 is 1 and field2 is null.
The result was the same.
Any idea how to do this?
It sounds like you need to make use of advanced where clauses.
Given that search in field1 and field2 is constant we will leave them as is, but we are going to adjust your search in datefield a little.
Try this:
$query = Model::where('field1', 1)
->whereNull('field2')
->where(function ($query) {
$query->where('datefield', '<', $date)
->orWhereNull('datefield');
}
);
If you ever need to debug a query and see why it isn't working, it can help to see what SQL it is actually executing. You can chain ->toSql() to the end of your eloquent query to generate the SQL.
You could merge two queries together:
$merged = $query_one->merge($query_two);
Using coalesce() converts null to 0:
$query = Model::where('field1', 1)
->whereNull('field2')
->where(DB::raw('COALESCE(datefield_at,0)'), '<', $date)
;
If you are confused about where to put the get()/first() for getting the collection or a single row here is the way:
$query = Model::where('field1', 1)
->whereNull('field2')
->where(function ($query) {
$query->where('datefield', '<', $date)
->orWhereNull('datefield');
}
)->get();

what the meaning mergeBindings in laravel

hy I'm new in laravel 4 and I have found code like this
$sub = Abc::where(..)->groupBy(..); // Eloquent Builder instance
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery())
->count();
my quetion is
1. what the meaning mergeBindings($sub->getQuery()) and give me example for using mergeBindings
assume your first query is like this:
$sub = Abc::where('type', 1)->groupBy(..);
then when we convert it to sql:
$sub->toSql();
this will return query string some thing like this:
SELECT * FROM abc where abc.type = ? GROUp BY ...
you can see the "?" as the type value which will be binded (replaced by 1) when the PDO executes that query string
So when we use that sub query in another query as you do in
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery())
->count();
you have converted the first sub query to sql string, BUT the second query does not know any thing about your first sub query binding which in this example the value 1
so we need to merge the binding from the first sub query into the last query
so that the last query when executes it will know the value 1 and binds it to the
where clause in replace of "?", and your final executed query will be something like this
(SELECT count(*) from abc where type = 1 GROUP BY ...) as sub
and thats it the use of mergeBindings() method
i hope this makes things clear for your question.
thanks,

mysql_num_rows() does not work with SUM()?

Using PHP mysql_num_rows() returns "1" when running the query below on the table below when there are no matching rows present.
Upon testing I found out that the problem happens when I use the SUM() function in the query. If I take SUM() out of the query mysql_num_rows() returns "0" like it should.
Is there something else I should use instead of mysql_num_rows() to find out if there is a matching row in the table?
Table:
name | students_money | grade
George | 5 | A
Bill | 10 | A
Dan | 7 | A
Code:
$sql = "SELECT SUM(students_money) AS sum_money FROM students_table WHERE name = 'Tom' AND name = 'Jack'";
$result = #mysql_query($sql, $con) or die(mysql_error());
$num_rows = mysql_num_rows($result);
if ($num_rows < 1) {
echo "not everyone has paid";
exit;
}
while($row = mysql_fetch_array($result)) {
$sum_money = $row[sum_money];
$total = $total + $sum_money;
}
SUM() is an aggregate function. It takes all the rows that are returned for a group and adds them up.
Since you do not have a GROUP BY clause, it is adding up the values of all rows, even if there are none. It is then returning the total as a single row, so there should only be 1 row.
If you clarify what you want returned, I can try to help you write a statement to return it.
mysql_num_rows() tells you the number of rows returned by the database query. There is always a one row return in your case because there is always one a sum. The sum may be 0 of course.
It may be a good idea to test your query in the mysql query browser. Perhaps you are looking for something like this?
SELECT name, SUM(students_money) AS sum_money
FROM students_table
GROUP BY name;
This will group the sums on a per name basis. To skip 0 sums you can add this:
HAVING sum_money > 0;

Categories