I have a customer_invoices table containing a fields invoiced_at as date & total_price, I need the SUM of the total_price of the invoices from the start of each year till the same day as today, grouped by year, and starting from a specific year that I provide.
What I did so far :
public function totalIncomeToCurrentDayByYear($startingAt)
{
return CustomerInvoice::selectRaw('sum(total_price) as total')
->where('customer_invoices.status', Status::VALIDATED)
->selectRaw("DATE_FORMAT(invoiced_at,'%Y') as year")
->whereRaw("DATE_FORMAT(invoiced_at,'%Y') >= $startingAt")
->groupBy('year')
->get()
->pluck('total', 'year');
}
I need to have a result similar to this : (in this case I get the SUM of the whole year which is Not what I want):
totalIncomeToCurrentDayByYear(2003); // ==>
#items: array:14 [▼
2003 => "144.52"
2006 => "11455.00"
2007 => "27485.40"
2008 => "39268.08"
2009 => "37434.19"
2010 => "443631.75"
2011 => "2275159.26"
2012 => "3874576.94"
2013 => "4994901.19"
2014 => "5968874.72"
2015 => "7250182.95"
2016 => "9017509.81"
2017 => "10704557.00"
2018 => "12637778.13"
]
For example, today is January 23rd, for each line in the array should represent the SUM of total_price during that year up until January 23rd.
try below query
CustomerInvoice::whereRaw("DATE_FORMAT(invoiced_at,'%Y') >= $startingAt")
->where('customer_invoices.status', Status::VALIDATED)
->whereRaw('MONTH(invoiced_at) < MONTH(NOW()) or
(MONTH(invoiced_at) = MONTH(NOW()) and DAY(invoiced_at) <=
DAT(NOW()))')
->select(DB::raw('YEAR(invoiced_at) invoiced_year' ),
DB::raw('SUM(total_price) total_price'))-
>groupBY(DB::raw('YEAR(invoiced_at)')
->orderBy(DB::raw('YEAR(invoiced_at)')->get();
Put another where filter such that invoice date is less than current date.
public function totalIncomeToCurrentDayByYear($startingAt,$currentDate) { return CustomerInvoice::selectRaw('sum(total_price) as total') ->where('customer_invoices.status', Status::VALIDATED) ->selectRaw("DATE_FORMAT(invoiced_at,'%Y') as year") ->whereRaw("DATE_FORMAT(invoiced_at,'%Y') >= $startingAt")->whereRaw("invoiced_at <= $currentDate") ->groupBy('year') ->get() ->pluck('total', 'year'); }
Related
I'm trying to match all the rows in a table to a specific month. I want my output to look like this:
return [
'January' => [
'total_sales' => 100
],
'February' => [
'total_sales' => 50
],
'Match' => [
'total_sales' => 2
],
];
So the month period starts at the beginning of the year (January) and ends until today's date (April) if we are in June then I should see total sales from June, if we are in July same thing etc..
This is what I have so far to loop from the beginning of the year until today's month.
for($i=date('n');$i>0;$i--)
{
var_dump(date('F', mktime(0, 0, 0, ($i), 2, date('Y'))));
}
This is what I have to pull query from mySQL:
`SELECT * FROM total_sales WHERE created_at > (NOW() - INTERVAL {starts from January till today's month} MONTH)`
My Problem:
How do can I display the output I can to accomplish above?
You can group on month,
select date_format(created_at,"%b"),sum(sale_amount) from total_sales where created_at > '2020-01-01 00:00:00' group by date_format(created_at,"%b");
I posted a question some time ago on representing data per date horizontally on a datatable.
See here: datatables dates at the top and data cells going from left to right
With the help of that thread I was able to get the data to display how I wanted it. With the dates showing at the top, the service provided on the left and all data associated with any date between the 2 date paramters inside the main body. (If there is no data in a particular date then the < td > will display 0. See here:
http://www.phpwin.org/s/ewbAS6
After manipulating this code further I made the dates of the search dynamic by proving a form with a start date and an end date, and a dropdown with the options of:
Daily
Weekly
Monthly
Quaterly
Yearly
this allows the interval of dates at the top to become dynamic. Of course all this is doing is changing the value of the 2nd parameter inside the date while loop.
WHILE (strtotime($date) <= strtotime($end_date)) {
echo '<th>' . $date . '</th>';
$date = date('Y-m-d', strtotime($date . ' +1day'));
}
with the parameter set at Weekly, the value of +1day becomes +1week, at Monthly; the value becomes +1month and so on.
MY ISSUE:
When the interval is set to daily, the dates with their corresponding attendance counts are displayed correctly but once you try to increase the interval to +1week and above the data does not round up to the week shown. Check this:
[LINK1]Per day: http://www.phpwin.org/s/ewbAS6
[LINK2]Per month: http://www.phpwin.org/s/xRo3I6
Looking at the array (modified on the LINK2)
$result[] = array('Service Name' => 'Health', 'date' => '2017-04-04', 'Attendance' => 5);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-16', 'Attendance' => 5);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-04-03', 'Attendance' => 1);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-05-03', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-05-03', 'Attendance' => 2);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-11', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2018-04-03', 'Attendance' => 10);
You can see in the array that there are multiple attendance entries in April, totaling 14 Attendances in that month however during LINK2 where the interval is increased to a month instead of showing 14 for April (which would be the sum of all the dates in that particular month) it shows the value 1.
My live version takes the array from a database so I used the YEAR(), MONTH(), WEEK() and DAY() function on the date and used group by. The query executes how I want it but having issues working on the PHP end.
What would be the best way to find the difference in the two dates start_date and account_add_date then insert into a column called account_age?
What I need is for a user to select a start_date say its January.
Then the date when they added account_add_date say March.
The difference is 2 months so in account_age would be 2,
then in April that 2 would be a 3. May 4, June 5 and so on
Dose anyone know how to do this ?
My current insert query MODEL
function create_bank()
{
$this->load->helper('date');
$new_bank_acc_insert_data = array(
'bank_name' => $this->input->post('bank_name'),
'interest' => ($this->input->post('interest') / 100),
'start_amount' => $this->input->post('start_amount'),
'length' => $this->input->post('length'),
'start_date' => date('Y-m-d',strtotime($this->input->post('start_date'))),
'mem_id' => $this->session->userdata('id'),
'account_add_date' => $this->current_date()
);
$insert = $this->db->insert('bank', $new_bank_acc_insert_data);
return $insert;
}
Idea on finding account age
SELECT DATEDIFF('start_date','account_add_date')
SELECT
(
12* (YEAR(account_add_date) - YEAR(start_date)) +
(MONTH(account_add_date) - MONTH(start_date))
) AS differenceInMonth
FROM
YOUR_TABLE
Although DATEDIFF function returns the difference in two dates in days which is more accurate comparing to the difference in month
Explanation:
Example:
start_date = 2014 March
account_add_date = 2015 January
YEAR(account_add_date) = 2015
YEAR(start_date) = 2014
MONTH(account_add_date) = 1
MONTH(start_date) = 3
So according to the query:
12 * (2015-2014) + (1-3) = 12 * 1 - 2 = 10 (Months)
I have a contact table with date field for birthdate.
Now I would like to show list of birthday within next week. I can show it, but the order is based on the year.
How can I order the data, just based on month and day only?
$sideBarTaskSuggestion =
$this->Project->Contact->find('all', array(
'conditions' => array(
'Contact.group_id' => $this->Session->read('Auth.User.group_id'),
'Contact.birthdate NOT' => null,
'AND' => array(
array('Contact.birthdate NOT' => null),
array('Contact.birthdate + INTERVAL EXTRACT(YEAR FROM NOW()) -
EXTRACT(YEAR FROM Contact.birthdate) YEAR <=' => date('Y-m-d',
strtotime('+1 week'))),
array('Contact.birthdate + INTERVAL EXTRACT(YEAR FROM NOW()) -
EXTRACT(YEAR FROM Contact.birthdate) YEAR >=' => date('Y-m-d')),
)
),
'order' => 'Contact.birthdate DESC'
)
);
When you say you want 'order the data, just based on month and day only?', I assume you mean:
Nov 22, 2013
Oct 21, 1922
Mar 5, 2000
Jan 31, 2001
Jan 1, 1990
Then try this:
'order' => 'DAYOFYEAR(Contact.birthdate) DESC'
I am building a small class combination to calculate the precise date of the beginning of a semester. The rules for determining the beginning of the semester goes as follow :
The monday of week number ## and after dd-mm-yyyy date
ie: for winter its week number 2 and it must be after the january 8th of that year
I am building a resource class that contain these data for all the semesters (4 in total). But now I am facing an issue based on the public holidays. Since some of those might be on a Monday, in those cases I need to get the date of the Tuesday.
The issue I am currently working on is the following :
The target semester begins on or after august 30 and must be on week 35.
I also have to take account of a public holiday which happen on the first monday of september.
The condition in PHP terms is the following
if (date('m', myDate) == 9 // if the month is september
&& date('w', myDate) == 1 // if the day of the week is monday
&& date('d', myDate) < 7 // if we are in the first 7 days of september
)
What would be the best way to "word" this as a condition and store it in an array?
EDIT
I might not have been clear enough, finding the date is not the problem here. The actual problem is storing a condition in a configuration array that looks like the following :
$_ressources = array(
1 => array(
'dateMin' => '08-01-%',
'weekNumber' => 2,
'name' => 'Winter',
'conditions' => array()
),
2 => array(
'dateMin' => '30-04-%',
'weekNumber' => 18,
'name' => 'Spring',
'conditions' => array()
),
3 => array(
'dateMin' => '02-07-%',
'weekNumber' => 27,
'name' => 'Summer',
'conditions' => array()
),
4 => array(
'dateMin' => '30-08-%',
'weekNumber' => 35,
'name' => 'Autumn',
'conditions' => array("date('m', %date%) == 9 && date('w', %date%) == 1 && date('d', %date%) < 7")
)
);
The issue I have with the way it's presented now, is that I will have to use the eval() function, which I would rather not to.
You said:
The target semester begins on or after august 30 and must be on week 35.
If that's the case you can simple check for week number.
if(date('W', myDate) == 35)
Or if your testing condition is correct then you should compare day number till 7 as it starts from 1.
if((date('m', myDate) == 9 // september
&& date('w', myDate) == 1 // monday
&& date('d', myDate) <= 7 // first 7 days of september
)
And then in the if statement, once you have found the monday which would be OK IF its not a public holiday, do this
if(...){
while(!array_search (myDate, aray_of_public_holidays))
date_add($myDate, date_interval_create_from_date_string('1 days'));
}
Here the array_of_public_holidays contains the list of public holidays.
Update with Code
Following code should work for your purposes
<?php
// array with public holidays
$public_holidays = array(/* public holidays */);
// start on 30th august
$myDate = new DateTime('August 30');
// loop till week number does not cross 35
while($myDate->format('W') <= 35){
// if its a monday
if($myDate->format('w') == 1){
// find the next date not a public holiday
while(array_search($myDate, $public_holidays))
$myDate->add(date_interval_create_from_date_string('1 days'));
// now myDate stores the valid semester start date so exit loop
break;
}
// next date
$myDate->add(date_interval_create_from_date_string('1 days'));
}
// now myDate is the semester start date
?>
Update according to updated question
Following code should work for your needs. You do not need to store the condition in your array as PHP code. The following code shows how it can be done
// semester conditions
$sem_conditions = array(
1 => array(
'dateMin' => '08-01-%',
'weekNumber' => 2,
'name' => 'Winter'
),
2 => array(
'dateMin' => '30-04-%',
'weekNumber' => 18,
'name' => 'Spring'
),
3 => array(
'dateMin' => '02-07-%',
'weekNumber' => 27,
'name' => 'Summer'
),
4 => array(
'dateMin' => '30-08-%',
'weekNumber' => 35,
'name' => 'Autumn'
)
);
// array with public holidays format (d-M)
$public_holidays = array('05-09', '10-01');
// store sem starts
$sem_starts = array();
// for each semester
foreach($sem_conditions as $sem){
// start date
$myDate = date_create_from_format('d-m', substr($sem['dateMin'], 0, -2));
// loop till week number does not cross $sem['weekNumber']
while($myDate->format('W') <= $sem['weekNumber']){
// if its a monday
if($myDate->format('w') == 1){
// find the next date not a public holiday
while(array_search($myDate->format('d-m'), $public_holidays) !== false)
$myDate->add(date_interval_create_from_date_string('1 days'));
// now myDate stores the valid semester start date so exit loop
break;
}
// next date
$myDate->add(date_interval_create_from_date_string('1 days'));
}
// add to sem starts
$sem_start[$sem['name']] = $myDate->format('d-m-Y');
}
var_dump($sem_start);
The target semester begins on or after august 30 and must be on week 35
The start of the semester is the minimal date between week 35 and August 30:
$week35 = new DateTime("January 1 + 35 weeks");
$august30 = new DateTime("August 30");
$start = min($week35, $august30);
Alternatively:
$start = min(date_create("January 1 + 52 weeks"), date_create("August 30"));