I am trying to disperse the results of 3 queries in a very specific manner across any number of days. Each result from each array represents 1 phone call, and I want a total of 18 phone calls per day.
I need a total of 18 total results per day broken down by:
8 $active_costco results
4 $inactive_costso results
3 $bashas results
3 $afs results
$active_costco returns 321 total results
$inactive_costco returns 119 total results
$bashas returns 64 total results
$afs returns 47 results
I need the total number of results to be 18 per day, so if there are no more $afs or $inactive_costco's, fill in to 18 with $active_costcos.
Here is the php I have currently (it only divides the active_costcos across 8 per day)
$active_costco = sql::results($query);
$inactive_costco = sql::results();
$bashas = sql::results("");
$afs = sql::results("");
$date = date('Y-m-d');
$str = 'INSERT pharmacy.dbo.hotlist (employee_id, store_id, follow_up_date, created_at, status, urgency)VALUES';
for ($i = 0; $i < count($active_costco); $i++)
{
if ($i%8 == 0)
{
$date = date('Y-m-d', strtotime($date . '+1 Weekday'));
}
$str .= "('0CS',". $active_costco[$i]['id'] . ", '$date', '". date('Y-m-d H:m.s') . "', 1, 3)";
$str .= ($i == count($active_costco)-1)? '': ',';
$str .= '<br />';
}
echo $str;
Any help would be appreciated.
Thanks,
Mike
After spending a little time on this, here is the solution I came up with:
$str = 'INSERT pharmacy.dbo.hotlist (employee_id, store_id, follow_up_date, created_at, status, urgency)VALUES';
do
{
$date = date('Y-m-d', strtotime($date . " +1 Weekday"));
$today = array();
for ($i = 0; $i < 3; $i ++)
{
$basha = array_pop($bashas);
$associated = array_pop($afs);
if (!empty($basha))
$today[] = $basha;
if (!empty($associated))
$today[] = $associated;
}
for ($i = 0; $i < 4; $i++)
{
$inactive = array_pop($inactive_costco);
if (!empty($inactive))
$today[] = $inactive;
}
$count = 18 - count($today);
for ($i = 0; $i < $count; $i++)
{
$active = array_pop($active_costco);
if (!empty($active))
$today[] = $active;
}
$calls_left = count($active_costco) + count($inactive_costco) + count($bashas) + count($afs);
foreach ($today as $v)
{
echo "Store ID = " . $v['id'] . " Date = " . $date . "<br />";
}
}while ($calls_left > 0);
It goes through and pops elements off each of the arrays (the number that was specified). If it the array is empty (there is nothing to pop) it doesn't add anything. Then it counts the number of calls in the today array, subtracts that from 18, and grabs the remaining calls from $active_costsco.
Thanks to everyone that put in input.
Related
I have this query now:
SELECT DATE_FORMAT(`dataNl`, \'%Y%m\') AS `Ym`, COUNT(*) AS `totale`
FROM `noleggio`
GROUP BY `Ym`
This help to get data for each month, but if a month with 0 value, this doesn't exist in the database, so I can't get it. I need a query that add remaining month setting the COUNT field to 0.
I made a PHP code to add months with 0 value into the array, but it only works if the year is only one, if I want to get more, this needs a lot of tricky code, I think there could be a solution with SQL.
This is the PHP code:
$t = array();
$m = array();
foreach ($months as $val) {
$t[] = $val['totale'];
$m[] = $val['Ym'];
}
for ($i = 0; $i < 12; ++$i) {
if (in_array($i + 201801, $m) == false) {
array_splice($t, $i, 0, 0);
}
}
Here is a PHP solution which requires min and max dates from the database:
// use the query SELECT MIN(dataNl), MAX(dataNl) FROM ... to
// find the first and last date in your data and use them below
$dates = new DatePeriod(
DateTime::createFromFormat('Y-m-d|', '2018-01-15')->modify('first day of this month'),
new DateInterval('P1M'),
DateTime::createFromFormat('Y-m-d|', '2018-12-15')->modify('first day of next month')
);
// assuming $rows contain the result of the GROUP BY query...
foreach ($dates as $date) {
$datestr = $date->format('Ym');
$index = array_search($datestr, array_column($rows, 'Ym'));
if ($index === false) {
echo $datestr . ' -> 0' . PHP_EOL;
} else {
echo $datestr . ' -> ' . $months[$index]['totale'] . PHP_EOL;
}
}
Try the below query:
SELECT DATE_FORMAT(`dataNl`, \'%Y%m\') AS `Ym`, COUNT(*) AS `totale`
FROM `noleggio`
GROUP BY MONTH(`dataNl`)
i have a age data:
18,25,36,20,23,21,31,
Using php how i can show like this data?
10 to 20 years = 1 people, 20 to 30 years = 4 people, 30 to 40 years = 2 people
You could try something like this. It uses array_map to divide all values in the data by 10 (thus putting them in groups), then array_count_values to count the number of people in each group.
$ages = [18,25,36,20,23,21,31];
$groups = array_count_values(array_map(function ($v) { return (int)($v / 10); }, $ages));
for ($i = 0; $i <= max(array_keys($groups)); $i++) {
echo $i*10 . " to " . ($i*10+9) . " years: " . (isset($groups[$i]) ? $groups[$i]: 0) . "\n";
}
Output:
0 to 9 years: 0
10 to 19 years: 1
20 to 29 years: 4
30 to 39 years: 2
Update
If you don't want to display groups that have no people in them, use this loop instead:
for ($i = 0; $i <= max(array_keys($groups)); $i++) {
if (isset($groups[$i])) echo $i*10 . " to " . ($i*10+9) . " years: " . $groups[$i] . "\n";
}
Output:
10 to 19 years: 1
20 to 29 years: 4
30 to 39 years: 2
Demo on 3v4l.org
There are many ways but I will prefer directly from mysql query, Something like this
SELECT IF (`age` < 10, '0 to 10 years',
IF(`age` > 10 AND `age` < 20, '10 to 20 years',
IF(`age` > 20 AND `age` < 30, '20 to 30 years', 'more than 30 years')
)
) AS age_group,
count(*) as `counts`
FROM `table_name`
Group by `age_group`
You can refer this answer to calculate age from DOB stored in database
$ages = [18,25,36,20,23,21,31];
$years = array(); // floor range
foreach ($ages as $age)
{
$m = (int)($age / 10);
(isset($years[($m*10)])) ? $years[($m*10)]++ : $years[($m*10)] = 1;
}
var_dump($years); // output: array(3) { [10]=> int(1) [20]=> int(4) [30]=> int(2) }
This code collected the birthday dates from your database and groups them for you in your desired ranges.
//Please update this section to grant access to your database
$username = 'root'; //Your Database Username
$password = ''; //Your Database Password
$database = 'test_sample'; //Your Database Name
$table_name = 'ages'; //Your Table Name
$column_name = 'date_of_birth'; // The Column where the birthday dates can be accessed
$query = 'SELECT `'.$column_name.'` FROM `'.$table_name.'`';
$db_connection = mysqli_connect('localhost', $username, $password, $database);
$result = mysqli_query($db_connection, $query);
$current_ages = [];
$now = new DateTime();
while($data = mysqli_fetch_array($result)) {
$date = new DateTime($data[$column_name]);
$interval = $now->diff($date);
$current_ages[] = $interval->y;
}
// $current_ages = [18,25,36,20,23,21,31];
$desired_range = [
[10,20], [21,30], [31,40], [41,50]
];
$result = [];
foreach($current_ages as $data) {
foreach($desired_range as $index => $range) {
if($data >= $range[0] && $data <= $range[1]) {
(isset($result[$index]))? $result[$index]++ : $result[$index] = 1;
break;
}
}
}
foreach($desired_range as $index => $range) {
$count = (isset($result[$index]))? $result[$index] : 0;
echo $range[0]." to ".$range[1]." years = ".$count.' <br/>';
}
I have a MySql table where I saved all workers names and the dates workers have to work on. I want to show a list containg all days of the current month and the worker names who have to work on the day that corresponds to them. Example:
February
1
2
3 - John Wick
5
6 - Martha Beck
etc.
This is the code I have in PHP but the loop is not working. I just get a list from 1 to 30 but it is not showing the data from database. If I run the loop without the (while ($n < 31)), I get all the records from database but I want to show the names just beside the day that correspond.
<?php
mysql_select_db($database_nineras, $nineras);
$query_res = sprintf("SELECT res_id, res_dateini, res_datefin, res_name FROM reservas ORDER BY res_dateini DESC");
$reservas = mysql_query($query_res, $nineras) or die(mysql_error());
$rreser = mysql_fetch_assoc($reservas);
$treser = mysql_num_rows($reservas);
$n = 1;
while ($n < 31) {
do {
++$n;
if ($n == date('d', strtotime($rreser['res_dateini']))) {
echo $n . ' - ' . $rreser['res_name'];
}
else {
echo $n;
}
} while ($rreser = mysql_fetch_assoc($reservas));
}
?>
The problem with your code is that the do-while loop is fetching all the rows returned by the query. So when you get to the second iteration of the while loop there's nothing left to fetch.
Rather than fetch the rows from the database each time through the loop, you can fetch them once and put them into an array whose index is the day numbers. Then you can loop through the days and print all the rows for each day.
Use date('j', ...) to get the date without a leading zero. Or change your SQL query to return DAY(res_dateini).
$results = array();
$reservas = mysql_query($query_res, $nineras) or die(mysql_error());
while ($rreser = mysql_fetch_assoc($reservas)) {
$d = date('j', strtotime($rreser['res_dateini'])));
$results[$d][] = $rreser['res_name'];
}
for ($day = 1; $day <= 31; $day++) {
echo "$day - " . (isset($results[$day]) ? implode(", ", $results[$day]) : "") . "<br>\n";
}
DEMO
I've been trying to make a list of days of when I went to school and when I didn't.
I'm looping the days here. Another array contains the days I didn't go to school.
<?php
$fecha1 = "2015-03-10";
$fecha2 = date("Y-m-d",strtotime($fecha1."+ 10 days"));
$fecha3 = array("2015-03-11","2015-03-14","2015-03-17");
$j=1;
for($i=$fecha1;$i<$fecha2;$i = date("Y-m-d", strtotime($i ."+ 1 days"))){
for ($n=0; $n <count($fecha3) ; $n++) {
if($i==$fecha3[$n]){
$obs="not there";
}else{
$obs="there";
}
}
echo "Day ".$j." ".$i."---".$obs."<br />";
$j++;
}
?>
and the output is
Day 1 2015-03-10---there
Day 2 2015-03-11---there
Day 3 2015-03-12---there
Day 4 2015-03-13---there
Day 5 2015-03-14---there
Day 6 2015-03-15---there
Day 7 2015-03-16---there
Day 8 2015-03-17---not there
Day 9 2015-03-18---there
Day 10 2015-03-19---there
I dont understand why it doesnt say "not there" on day 2 2015-03-11
and day 5 2015-03-14, someone help me please I've been with this for hours.
You should add a break once the needle is found:
if($i==$fecha3[$n]){
$obs="not there";
break; // this is important
}else{
$obs="there";
}
Another alternative is also in_array() for searching:
if(in_array($i, $fecha3)){
$obs="not there";
}else{
$obs="there";
}
It's because 2015-03-11 and 2015-03-14 are the first two values in the $fecha3 array, and $obs gets overwritten in that second for loop.
In this case I would recommend using in_array() instead of a second for loop:
$fecha1 = '2015-03-10';
$fecha2 = 10;
$fecha3 = array('2015-03-11', '2015-03-14', '2015-03-17');
for ($i = 0; $i < $fecha2; $i++) {
$date = date('Y-m-d', strtotime($fecha1 . ' + ' . $i . ' days'));
$obs = in_array($date, $fecha3) ? 'not there' : 'there';
echo 'Day ' . ($i + 1) . ' ' . $date . '---' . $obs . '<br />';
}
I have written a round robin tournament generator in PHP for an online electronic sports league, and I need to calculate the dates for each game in the tournament. Games are played every Thursday and Sunday over the course of many weeks (the number of weeks is dependent on how many teams are participating). Given the starting week and the number of weeks what would be the best way to calculate those dates?
I'm guessing it requires using some combination of DateTime, DateInterval, and DatePeriod; but I am having trouble figuring out how it would be done.
Update:
Apologies for not providing the code before. Here is the solution I had originally come up with. I didn't know if there was a simpler way of doing it. The function was called submitSchedule where the dates were generated.
<html>
<body>
<?php
function roundRobin($teams) {
$len = count($teams);
$schedule = array();
for ($i = 0; $i < $len - 1; $i++)
{
$home = array_slice($teams, 0, $len / 2);
$away = array_slice($teams, $len / 2);
$day = array();
for ($j = 0; $j < $len / 2; $j++)
{
array_push($day, array($home[$j], $away[$j]));
}
array_push($schedule, $day);
$temp = $away[0];
for ($j = 0; $j < count($away) - 1; $j++)
{
$away[$j] = $away[$j + 1];
}
$away[count($away) - 1] = $home[count($home) - 1];
for ($j = count($home) - 1; $j > 1; $j--)
{
$home[$j] = $home[$j - 1];
}
$home[1] = $temp;
$teams = array_merge($home, $away);
}
return $schedule;
}
function roundRobinBalanced($teams)
{
$schedule = roundRobin($teams);
for ($i = 1; $i < count($schedule); $i+=2)
{
$schedule[$i][0] = array_reverse($schedule[$i][0]);
}
return $schedule;
}
function doubleRoundRobinBalanced($teams)
{
$sched2 = roundRobinBalanced($teams);
for ($i = 0; $i < count($sched2); $i++)
{
$sched2[$i] = array_reverse($sched2[$i]);
}
return array_merge(roundRobinBalanced($teams), $sched2);
}
function tripleRoundRobinBalanced($teams)
{
return array_merge(doubleRoundRobinBalanced($teams), roundRobinBalanced($teams));
}
function submitSchedule($schedule, $start, $intervals, &$con)
{
mysqli_query($con, "TRUNCATE TABLE matches");
$curDate = $start;
echo "<pre>";
for ($i = 0; $i < count($schedule); $i++)
{
for ($j = 0; $j < count($schedule[$i]); $j++)
{
$temp0 = $schedule[$i][$j][0];
$temp1 = $schedule[$i][$j][1];
$temp2 = date_format($curDate, "Y-m-d");
mysqli_query($con,"INSERT INTO matches (T1ID, T2ID, gameDate) VALUES ('$temp0', '$temp1', '$temp2')");
echo "<span style=\"background:lightblue;\">( " . date_format(new DateTime(), "Y-m-d H:i:s") . " )</span>" . "> INSERT INTO matches (T1ID, T2ID, gameDate) VALUES (". $schedule[$i][$j][0] . ", " . $schedule[$i][$j][1] . ", \"" . date_format($curDate, "Y-m-d") . "\")<br>";
}
date_add($curDate, date_interval_create_from_date_string($intervals[$i % count($intervals)]));
}
echo "</pre>";
}
$teams = array();
$con=mysqli_connect("localhost:3306","root","REMOVED","schedule");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
//Select all items from the 'teams' table and order them first in descending order by points, then in ascending order by 'teamName'
$result = mysqli_query($con,"SELECT * FROM teams");
while($row = mysqli_fetch_array($result))
{
array_push($teams, $row['TID']);
}
if (count($teams) % 2 == 1)
{
array_push($teams, null);
}
shuffle($teams);
$schedule = tripleRoundRobinBalanced($teams);
// echo "<pre>" . json_encode($schedule, JSON_PRETTY_PRINT, JSON_FORCE_OBJECT) . "</pre>";
echo "<pre>";
print_r($schedule);
echo "</pre>";
// ---- List of possible DateTime expressions ----
// thursday
// next thursday
// YYYY-MM-DD
// DD/MM/yy
// thursday + 1 day
$start = new DateTime("thursday"); // Indicates the date of the first game
$jump = array("3 days", "4 days"); // Indicates the time intervals of each game (e.g. If day 1 starts on thursday, day 2 starts on sunday, day 3 starts on thursday, etc.)
submitSchedule($schedule, $start, $jump, $con);
mysqli_close($con);
?>
</body>
</html>
The way to achieve this is by using PHP's DateTime classes as you guessed. They are really very useful. I would suggest a little function something like this:-
/**
* #param $startWeek ISO week number of the first week
* #param $numWeeks The number of weeks to run including the first
*
* #return \DateTime[] An array of DateTime objects
*/
function getPlayDays($startWeek, $numWeeks)
{
$numWeeks --;
$result = [];
$currYear = (int)(new \DateTime())->format('Y');
$oneDay = new \DateInterval('P1D');
// Start on the first Thursday of the given week.
$startDate = (new \DateTime())->setISODate($currYear, $startWeek, 4);
$endDate = clone $startDate;
$endDate->add(new \DateInterval("P{$numWeeks}W"));
// End on the Sunday of the last week.
$endDate->setISODate((int)$endDate->format('o'), (int)$endDate->format('W'), 7);
$period = new \DatePeriod($startDate, $oneDay, $endDate->add($oneDay));
foreach($period as $day){
if(4 === (int)$day->format('N') || 7 === (int)$day->format('N') ){
$result[] = $day;
}
}
return $result;
}
foreach(getPlayDays(1, 3) as $playDay){
var_dump($playDay->format('D m-d-Y'));
}
You didn't specify how you would identify the starting week, so I have assumed an ISO week number.
Output:-
string 'Thu 01-02-2014' (length=14)
string 'Sun 01-05-2014' (length=14)
string 'Thu 01-09-2014' (length=14)
string 'Sun 01-12-2014' (length=14)
string 'Thu 01-16-2014' (length=14)
string 'Sun 01-19-2014' (length=14)
See it working.
DateTime manual.
This function will quite happily cope with DST changes, leap years and weeks close to the start and end of the year thanks to the built in magic of the DateTime classes :)
proof or STFU.
Have a look at the strtotime function:
http://www.php.net/manual/en/function.strtotime.php
You could do something like this:
$startDate = "May 15, 2014";
$startDate = strtotime($startDate);
And you could get the start of the Sunday match by simply adding three days:
$nextDate = strtotime("+3 day", $startDate);
Your question is a bit vague, but I think this is what you were asking.
Let's say you have the timestamps of the day of starting week (06:00 AM time)...
Every other date will be 7 days (86400 seconds * 7) in the future.
Let's assume you will run this for 52 weeks (1 year)
$firstThu = 1234567890;
$firstSun = 9876543210;
$nextThus = array();
$nextSuns = array();
for($i=0; $i<52; $i++) {
$nextThus[] = date('d/m/Y', $firstThu + (86400 * 7 * $i));
$nextSuns[] = date('d/m/Y', $firstSun + (86400 * 7 * $i));
}
At the end of the loop you will have two arrays with all the 52 weeks dates.