Laravel GroupBy multiple columns with date - laravel

I have these fields in my table, I want get the data by month of the selected year & type_id, then SUM the amount on each month.
Ex: selectYear = 2019
Here is my account_table
id | type_id | amount | kind | created_at
1 | 2 | 200 | expense | 2019-01-15 10:14:31
2 | 2 | 400 | income | 2019-01-15 10:14:31
3 | 2 | 300 | expense | 2018-01-15 10:14:31
4 | 5 | 100 | expense | 2019-02-15 10:14:31
5 | 5 | 200 | income | 2019-03-15 10:14:31
this what I expected output.
if kind is expense the amount is -,
if kind is income the amount is +
Ex. on the month of Jan.
id 1 has 200 expense, and id 2 has 400 income
formula -200 + 400
Jan | Feb | Mar | ... so on
200 | 100 | 200 | ... so on
I hope I delivered and explain well, I am stuck on this functions, please I need help,
UPDATE.
Expected OUTPUT
Thanks in advance.

first, you must define or parse your year and month to numeric value. ex : January become 01, February become 02 etc.
in example :
$year = 2019;
$month = 01;
And you can use this :
$total = 0;
$data = DB::table('account_table')->whereMonth('created_at',$month)->whereYear('created_at',$year)->where('type_id',$type_id)->get;
foreach($data as $value){
if($value->kind == 'income'){
$total += $value->amount;
else{
$total -= $value->amount;
}
}
return $total;

Try following query on your account table:
Account::select(
DB::raw('SUM(IF(kind = "expense", amount * -1, amount)) as sum'),
DB::raw('YEAR(date) as year'),
DB::raw('MONTH(date) as month'),
)
->where('type', $type)
->where(DB::raw('YEAR(date)'), $selectYear)
->groupBy(DB::raw('MONTH(date)'));
You will get data like this:
[
[ sum: 400, year: 2020, month: 7, ]
[ sum: 500, year: 2020, month: 8, ]
...
]

Related

How to add category to column in Power BI?

I have data similar to this format:
customerName | Type of Sale | Sales Amount | Unit Purchased
-------------------------------------------------------------------
A | Online | 1500 | 4
B | Offline | 2000 | 5
C | Online | 3000 | 4
D | Offline | 4000 | 4
and I want data in following format in Power BI in Matrix Format
Metric | Sales Amount | Units Purchased
-----------------------------------------------------------
Customer Name | Online | Offline | Online | Offline
-----------------------------------------------------------
A | 15000 | 0 | 4 | 0
B | 0 | 2000 | 0 | 5
We can achieve this kind of visualization, but this needs some steps (more effort, Lower performance compared to the standard design.)
First we need an additional table with lables "Sales Amount" and "Units Purchased".
Relationship many to many.
Add additional measures:
Offline =
var sale = CALCULATE(sum('Sales'[Sales Amount]), FILTER(ALL('Sales'[Type of Sale]), 'Sales'[Type of Sale] = "Offline"))
var purch = CALCULATE(sum('Sales'[Unit Purchased]), FILTER(ALL('Sales'[Type of Sale]), 'Sales'[Type of Sale] = "Offline"))
return
if (SELECTEDVALUE('Lables'[LableName]) = "Purchase",purch,sale)
Online =
var sale = CALCULATE(sum('Sales'[Sales Amount]), FILTER(ALL('Sales'[Type of Sale]), 'Sales'[Type of Sale] = "Online"))
var purch = CALCULATE(sum('Sales'[Unit Purchased]), FILTER(ALL('Sales'[Type of Sale]), 'Sales'[Type of Sale] = "Online"))
return
if (SELECTEDVALUE('Lables'[LableName]) = "Sales Amount", sale,purch)

Concanate two or more rows from result into single result on CI activerecord

I have situation like this, I want to get value from database(this values used comma delimited) from more than one rows based on month and year that I choose, for more detail check this out..
My Schedule.sql :
+---+------------+-------------------------------------+
|ID |Activ_date | Do_skill |
+---+------------+-------------------------------------+
| 1 | 2020-10-01 | Accountant,Medical,Photograph |
| 2 | 2020-11-01 | Medical,Photograph,Doctor,Freelancer|
| 3 | 2020-12-01 | EO,Teach,Scientist |
| 4 | 2021-01-01 | Engineering, Freelancer |
+---+------------+-------------------------------------+
My skillqmount.sql :
+----+------------+------------+-------+
|ID |Date_skill |Skill |Price |
+----+------------+------------+-------+
| 1 | 2020-10-02 | Accountant | $ 5 |
| 2 | 2020-10-03 | Medical | $ 7 |
| 3 | 2020-10-11 | Photograph | $ 5 |
| 4 | 2020-10-12 | Doctor | $ 9 |
| 5 | 2020-10-01 | Freelancer | $ 7 |
| 6 | 2020-10-04 | EO | $ 4 |
| 7 | 2020-10-05 | Teach | $ 4 |
| 8 | 2020-11-02 | Accountant | $ 5 |
| 9 | 2020-11-03 | Medical | $ 7 |
| 10 | 2020-11-11 | Photograph | $ 5 |
| 11 | 2020-11-12 | Doctor | $ 9 |
| 12 | 2020-11-01 | Freelancer | $ 7 |
+----+------------+------------+-------+
In my website I want to make calculation with those two table. So if in my website want to see start from date 2020-10-01 until 2020-11-01 for total amount between those date, I try to show it with this code :
Output example
+----+-----------+-----------+---------+
|No |Date Start |Date End |T.Amount |
+----+-------- --+-----------+---------+
|1 |2020-10-01 |2020-11-01 |$ 45 | <= this amount came from $5+$7+$5+$7+$5+$9+$7
+----+-------- --+-----------+---------+
Note :
Date Start : Input->post("A")
Date End : Input->post("B")
T.Amount : Total Amount based input A and B (on date)
I tried this code to get it :
<?php
$startd = $this->input->post('A');
$endd= $this->input->post('B');
$chck = $this->db->select('Do_skill')
->where('Activ_date >=',$startd)
->where('Activ_date <',$endd)
->get('Schedule')
->row('Do_skill');
$dcek = $this->Check_model->comma_separated_to_array($chck);
$t_amount = $this->db->select_sum('price')
->where('Date_skill >=',$startd)
->where('Date_skill <',$endd)
->where_in('Skill',$dcek)
->get('skillqmount')
->row('price');
echo $t_amount; ?>
Check_model :
public function comma_separated_to_array($chck, $separator = ',')
{
//Explode on comma
$vals = explode($separator, $chck);
$count = count($vals);
$val = array();
//Trim whitespace
for($i=0;$i<=$count-1;$i++) {
$val[] .= $vals[$i];
}
return $val;
}
My problem is the result from $t_amount not $45, I think there's some miss with my code above, please if there any advice, I very appreciate it...Thank you...
Your first query only return 1 row data.
I think you can do something like this for the first query.
$query1 = $this->db->query("SELECT Do_skill FROM schedule WHERE activ_date >= $startd and activ_date < $startd");
$check = $query1->result_array();
$array = [];
foreach($check as $ck){
$dats = explode(',',$ck['Do_skill']);
$counter = count($dats);
for($i=0;$i<$counter;$i++){
array_push($array,$dats[$i]);
}
and you can use the array to do your next query :)
The array $dcek has the values
Accountant,Medical,Photograph
The query from Codeigniter is
SELECT SUM(`price`) AS `price` FROM `skillqmount`
WHERE `Date_skill` >= '2020-10-01' AND
`Date_skill` < '2020-11-01' AND
`Skill` IN('Accountant', 'Medical', 'Photograph')
which returns 17 - this matches the first three entries in your data.
Your first query will only ever give one row, even if the date range would match multiple rows.

How can i get all date even dates that don't have a record by eloquent with group by?

I have a method that get a month parameter to select rows of that month from users table. I want to show count of registered user for a month.
public function registeredUsersDaily($month)
{
$countOfDailyRegisteredUsersForAMonth = User::user()
->where(DB::raw('created_at'), '=', $month)
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE(created_at) as date'),
DB::raw('COUNT(*) as count')
]);
dd($countOfDailyRegisteredUsersForAMonth);
}
It return count only for dates that exists in users table, so i want to have zero for dates that don't exists.
|date|count|
| 5 | 10 |
| 15 | 3 |
I want to have a result like this:
|date |count |
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 10 |
| 6 | 0 |
| 7 | 0 |
| 8 | 0 |
| 9 | 0 |
| 10 | 0 |
| 11 | 0 |
| 12 | 0 |
| 13 | 0 |
| 14 | 0 |
| 15 | 3 |
....
Please check out like this
$dateValues = array_column($countOfDailyRegisteredUsersForAMonth, "date");
$maxDate = max($dateValues);
$likeYouWant=[];
for ($i = 1; $i <= $maxDate; $i++)
{
$likeYouWant[] = ["date" => $i, "count" => in_array($i, $dateValues) ? $countOfDailyRegisteredUsersForAMonth[array_search($i, $dateValues)]["count"] : 0];
}
print_r($likeYouWant);
If you want default date than you can mention in that migration file or you can also do that in your model from where you can retrieve data when there is no date given by user.
You can also refer this for more
How to pass default values to controller by routing in Laravel 5?
From what I've got from the comments:
I think the best thing here is to count the number of users created each day of the month. This will get you zero's in case no one registered on a given date.
With this, you'd probably loop through the dates checking the total users registered each date.
For instance, let's try to get the users created the last 30 days from now:
$results = [];
$startOfDay = now()->createMidnightDate();
for($i=0; $i<=30; $i++)
{
$total_count = User::whereBetween('created_at', [$startOfDay->subDays($i-1), $startOfDay->subDays($i)])
->count();
array_push($results[ $startOfDay->subDays($i)->format('d')], $total_count);
}
With this I think you can now work with the results from the array.

Laravel 5.2 Select Where Has Related Count Data

I have a table called 'templates' and 'details' that has relation templates has many details at my model.
i create a list template table with a filter number or detail, when i input 5 to the filter box, then table only show the templates that has 5 details.
how to do this?
this is my table structure :
templates
id | name | width | heigh
1 | A-5 | 112 | 100
2 | A-4 | 225 | 200
details
template_id | x | y
1 | 10 | 10
1 | 20 | 10
2 | 10 | 10
2 | 20 | 10
$templates = Template::whereHas( 'details', function( $detail ) {
$detail->selectRaw( 'count(id) as aduh' )->whereRaw( 'count(id) = 100' )->groupBy( 'id' );
} );
I think this should work:
$templates = Template::has('details', '=', 5)->get();
This will return all Templates that has 5 details.

datamapper, how do you filter a date field by month and year?

using datamapper, how do you filter a date field by month and year?
I can filter all records with today's date.
:date => Date.today
but i am curious if there is an elegant solution
for returning all records from december 2012.
posts.all
+----+------------+
| id | date |
+----+------------+
| 1 | 2009-10-20 |
| 2 | 2012-11-18 |
| 3 | 2012-12-10 |
| 4 | 2012-12-14 |
+----+------------+
posts.all(:date => Date.today)
+----+------------+
| id | date |
+----+------------+
| 4 | 2012-12-14 |
+----+------------+
I think your best bet is to use the date range form (which will result in an SQL "BETWEEN" query):
posts.all(:date => (Date.parse('2012-12-01') .. Date.parse('2012-12-31')))
For other years/months you'll have to lookup or compute the last date of the month instead of hardcoding them as in the example above.
def month_range(year, month)
d0 = Date.parse([year, month, 1].join('-'))
(d0 .. (d0>>1)-1)
end
posts.all(:date => month_range(2012, 12))

Resources