I have something like this in my MySQL DB.
Date product
2015-01-01 1
2015-01-01 2
2015-02-03 3
2015-02-04 1
2015-02-04 1
2015-02-04 3
What i need in PHP is to know which product was how often sold on which day.
So: 01.01.2015 Product 1 one time, product 2 one time, on 04.02.2015 product 1 two times, product 3 one time ...
Like this:
Date product 1 product 2 product 3
2015-01-01 1 1 0 //how many times
2015-02-03 0 0 1
2015-02-04 2 0 1
So i did a normal query: SELECT date from table order by date.
I get the object as stdClass in a array back, but now i am stuck with how to get the information out i need.
I tried something like
$array=array();
foreach ($result as $key => $value) {
$time = ($result[$key]->date);
$temp[] = array(
'date' => $time,
'product 1' => '2', //equals times
'product 2' => '3',
'product 3' => '4',
'product 4' => '4'
);
$arrayBig[] = $temp;
}
And also used array_count_values to filter the days to know which days appears, but i can not find out how to connect the product to the days.
EDIT: DWright's solution:
SELECT product, date, COUNT(*)
FROM tablename
GROUP BY product, date.
Date product count(*)
2015-01-01 1 1
2015-01-01 2 2
2015-02-03 3 1
Worked fine, now i have in each row which product was sold in which date how often.
The problem i encounter now is that if i want use this data to populate google stacked charts as seen below each row in the results represents on column in the google charts graph. So for the example above i will have two entries on 01.01.2015 in my charts (one bar for product 1 and one for product 2) but i want the amount of products on each day to be stacked. So there should be only one entry for 01.01.2015 where the amount of product 1 sold on that day and the amount of product 2 sold that day is stacked onto each other,
$result = $sql statement
foreach ($result as $key => $value ) {
$typeOfProduct = $value->product;
$amount = $value->anzahl;
$time = $value->Date;
switch ($typeOfProduct) {
case 1:
$produt1 = $amount;
break;
case 2: //twitter
$product2 = $amount;
break;
case 3:
$product3 = $amount;
break;
default:
break;
}
$rows = array();
$table = array();
$table['cols'] = array(
array('label' => 'Datum', 'type' => 'date'),
array('label' => 'product 1', 'type' => 'number'),
array('label' => 'product 2', 'type' => 'number'),
array('label' => 'product 3', 'type' => 'number')
);
$day = date('d', strtotime( $time ) );
$month = date('m', strtotime( $time ) );
$monthNew = $month - 1;
$year = date('Y', strtotime( $time ) );
$temp[] = array('v' => "Date( $year, $monthNew, $day )");
$temp[] = array('v' => $product1 );
$temp[] = array('v' => $product2);
$temp[] = array('v' => $product3 );
$rows[] = array('c' => $temp);
$table['rows'] = $rows;
}
This would result in something like this:https://jsfiddle.net/api/post/library/pure/
But i would need the values to be stacked onto each other , like this:
https://jsfiddle.net/api/post/library/pure/
This will be a lot easier for you to do in SQL. Something like:
SELECT product, date, COUNT(*)
FROM tablename
GROUP BY product, date.
Then each row is for one product by date, with the count sold that date.
Related
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.
I am try to get a row of rep names as column headings and then under that heading the top ten sales items per that rep
I am try to get data to output like this:
RepName1 RepName2 RepName3 RepName4
(rep names come from Database and will never be a set number)
Underneath each rep name in the column their top ten selling items in descending order
Like so:
RepName1
(top selling info will be pulled from database)
1st selling item
2nd selling item
3rd selling item
4th selling item
5th selling item
6th selling item
7th selling item
8th selling item
9th selling item
10th selling item
Then start a new column with the next rep and his or her top ten sellers.
$qry = "SELECT sales_rep_login FROM sales_reps WHERE status = 'A'";
$return_reps = mysql_query($qry);
$reps = array();
while($repX = mysql_fetch_assoc($return_reps)) {
$reps[] = $repX['sales_rep_login'];
}
foreach ($reps as $rep){
$q="SELECT sales_quantity.style_num, sales_quantity.number_sold, sales_reps.fname, sales_reps.lname FROM catalog JOIN sales_quantity ON catalog.style_num = sales_quantity.style_num
JOIN sales_reps ON sales_quantity.sales_rep_login = sales_reps.sales_rep_login
WHERE catalog.status = 'A'
AND catalog.season_id = '" . $_POST['season'] . "'
AND sales_quantity.sales_rep_login = '" .$rep. "'
AND sales_reps.status = 'A'
ORDER BY sales_quantity.number_sold DESC LIMIT 10";
$return_sales = mysql_query($q);
$Total_Sales = array();
while($Sales=mysql_fetch_assoc($return_sales))
$Total_Sales[] = $Sales;
} // end foreach
for some reason I am only getting the info for the very last rep.
Thanks in advance
You are overwriting $total_Sales array. Define it before foreach.
$Total_Sales = array(); // define array here
foreach ($reps as $rep){
$q="SELECT sales_quantity.style_num, sales_quantity.number_sold, sales_reps.fname, sales_reps.lname FROM catalog JOIN sales_quantity ON catalog.style_num = sales_quantity.style_num
JOIN sales_reps ON sales_quantity.sales_rep_login = sales_reps.sales_rep_login
WHERE catalog.status = 'A'
AND catalog.season_id = '" . $_POST['season'] . "'
AND sales_quantity.sales_rep_login = '" .$rep. "'
AND sales_reps.status = 'A'
ORDER BY sales_quantity.number_sold DESC LIMIT 10";
$return_sales = mysql_query($q);
while($Sales=mysql_fetch_assoc($return_sales))
$Total_Sales[$rep][] = $Sales; // make 2 dimensional array
}
Print $Total_Sales and see it it has all the values.
Use mysqli instead of mysql which is depreciated.
Considering the result array as
$Total_Sales = array
(
'RepName1' => array(
array('names' => '1st selling item','style' => 'DD39050BG','num' => '660'),
array('names' => '2nd selling item','style' => 'DD39043','num' => '600'),
array('names' => '3rd selling item','style' => 'DD79021','num' => '582')
),
'RepName2' => array(
array('names' => '1st selling item','style' => 'DD39050BG','num' => '660'),
array('names' => '2nd selling item','style' => 'DD39043','num' => '600'),
array('names' => '3rd selling item','style' => 'DD79021','num' => '582')
),
'RepName3' => array(
array('names' => '1st selling item','style' => 'DD39050BG','num' => '660'),
array('names' => '2nd selling item','style' => 'DD39043','num' => '600'),
array('names' => '3rd selling item','style' => 'DD79021','num' => '582')
),
);
Use the below code to display
<table cellpadding="5" cellspacing="5" border="1 sold #ccc">
<tr>
<?php foreach($Total_Sales as $key=>$value){
echo "<td>".$key;
if(is_array($value) && count($value)>0){
echo "<table>";
foreach($value as $k=>$v){
echo "<tr><td>".$v['names']."</td></tr>";
}
echo "</table>";
}
echo "</td>";
}?>
</tr>
</table>
I assume the php/cakephp/sql parliance.
I have a History table which contains the column created of type DATETIME.
I would show all the records of the History but arranged by day.
------------------------------------------
id created what
------------------------------------------
1 2014-01-01 08:00:00 Someone ran
2 2014-01-01 09:00:00 Someone cried
2 2014-01-02 10:00:00 Someone spoke
2 2014-01-02 18:00:00 Someone worked
And the result I am looking for
array(
'2014-01-01' => array(
0=>array('time'=>'8:00','what'=>'Someone ran'
1=>array('time'=>'9:00','what'=>'Someone cried'
),
'2014-01-02' => array(
0=>array('time'=>'10:00','what'=>'Someone spoke',
1=>array('time'=>'18:00','what'=>'Someone worked',
)
)
I am totaly stucked. Which SQL statement should I investigate? GROUP is not good...
If the other reviewers agree, I would give my answer in cakephp adapted from this SO answer
$histories = $this->History->find('all',
array(
'group'=>array('History.created')
));
foreach ($histories as $item) {
$key = date('Y-m-d',strtotime($item['History']['created']));
if (!isset($groups[$key])) {
$groups[$key] = array(
'items' => array($item),
'count' => 1,
);
} else {
$groups[$key]['items'][] = $item;
$groups[$key]['count'] += 1;
}
}
I have a following table display
Task No. Person Company Project Task Date Tracked Total Time Comments
14.1 vaish, arpit ABC-TecHolding Relaunch Websitnalysis 2013-02-12 19:21:03
14.2 vaish, arpit Sugarion New Opensource Server 2013-02-12 19:21:03
14.6 vaish, arpit Sugarion New Opensource Server 2013-02-12 19:21:03
5.26 Projectmanager, Paul ABC-Tec Holding Relaunch Website 2010-03-13 03:40:16
5.27 Projectmanager, Paul ABC-Tec Holding Relaunch Website 2010-03-12 03:40:16
5.27 Projectmanager, Paul ABC-Tec Holding Relaunch Website 2010-03-13 03:40:16
8.2 Worker, Willi Customers ACME Hosting Data transfer 2010-03-13 00:21:18
14.2 Worker, Willi Sugarion New Opensource Server 2013-02-06 00:21:18 fyhbvghjukjjkhhlhh uuiuijujj jookljh
This is my foreach loop
foreach($result123 as $key=>$task) {
$time=$this->addtime($task['name'],$range['start'],$range['end']); //to calculate total time per user in time range
$diff = $task['estimated']+$task['tracked'];
$diffSign = $diff > 0 ? '-' : '+';
$table->addRow(array(
'number' => $task['tasknumber'].' '.$task['id_project'] ,
'person'=> $task['name'],
'customer' => $task['company'],
'project' => $task['project'],
'task' => $task['task'],
'date' => $task['date_tracked'],
'tracked' => $task['workload_tracked'],
'Total_Time' => $time,
'comment'=>$task['comment']
));
}
The column total time shows total of time tracked per person.
I want the total time should show only once per Person and not display again and again for each row.
Thanks in advance.
That's how I'd do it (Pseudocode) :
Set an array of "checked" people
Foreach record :
Is person in the "checked" array?
If yes, go on.
If no, display total AND add person to "checked" people.
And in PHP : (if I got it right)
$checked = array();
foreach($result123 as $key=>&$task) {
$time=$this->addtime($task['name'],$range['start'],$range['end']); //to calculate total time per user in time range
$diff = $task['estimated']+$task['tracked'];
$diffSign = $diff > 0 ? '-' : '+';
if (in_array($task['name'],$checked) $time =0;
else {
$checked[] = $task['name'];
}
$table->addRow(array(
'number' => $task['tasknumber'].' '.$task['id_project'] ,
'person'=> $task['name'],
'customer' => $task['company'],
'project' => $task['project'],
'task' => $task['task'],
'date' => $task['date_tracked'],
'tracked' => $task['workload_tracked'],
'Total_Time' => $time,
'comment'=>$task['comment']
));
}
$name = '';
foreach($result123 as $key=>$task) {
if ($name == $task['name']) {
$time = '';
}
elseif ($name != $task['name']) {
$time=$this->addtime($task['name'],$range['start'],$range['end']);
$name = $task['name'];
}
$diff= $task['estimated']+$task['tracked'];
$diffSign= $diff > 0 ? '-' : '+';
$table->addRow(array(
'number' => $task['tasknumber'].' '.$task['id_project'] ,
'person'=> $task['name'],
'customer' => $task['company'],
'project' => $task['project'],
'task' => $task['task'],
'date' => $task['date_tracked'],
'tracked' => $task['workload_tracked'],
'Total_Time' => $time,
'comment'=>$task['comment']
));
}
That should do it, I think.
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"));