SQL query inside a loop in a loop - php

Hey everybody. I am trying to print out a schedule with thirty minute intervals and would like to query a DB to get whatever thing is happening at that time. If i manually enter the time (hour, minute, am/pm(months, year, day work as is)) i get events. It's just when i let the query pull the time from the loop this doesnt work. Any ideas?
$day = date('d');
$year = date('Y');
$month = date('m');
$start = mktime(0,0,0);
$thing_query="SELECT thing FROM things WHERE day='$day' AND month='$month' AND year='$year' AND hour='$hour' AND minute='$minute' AND ampm='$am'";
$result=mysql_query($thing_query);
for($min = 0; $min < 24 * 60 * 60; $min += 30 * 60)
{
$hour=date("h", $start + $min);
$minute=date("i", $start + $min);
$am=date("A", $start + $min);
while ($row=mysql_fetch_array($result)) {
$thing = $row[0];
}
printf("<tr><td>%s</td><td>$thing</td></tr>",
date("g:i a", $start + $min));
}

Variable references in a string are only valid at assignment; they don't continue to update if you change those variables, so when you do
$thing_query="SELECT thing FROM things WHERE day='$day' AND month='$month' AND year='$year' AND hour='$hour' AND minute='$minute' AND ampm='$am'";
it's equivilent to
$thing_query="SELECT thing FROM things WHERE day='15' AND month='2' AND year='2011' AND hour='' AND minute='' AND ampm=''";
because $hour, $minute and $am haven't been set, and thus the query returns nothing.
Even if they were, updating the string won't update the database query; you'll need to call mysql_query() on the new string to get that data.
If you move the $thing_query= and $res= lines to just before the while loop this should work, although it will only return the last event in each timeslot, because you're overriding $thing each time you go through the loop. It will also continue to list an event in every timeslot until it reaches a new one, because you're not clearing $thing.
As Andy says, this isn't currently a very efficient way to do what you want, but since you're presumably just starting out I'm guessing its more important to you for now that it works rather than being efficient, so hopefully this helps for now.

I would imagine this is because you are not setting hour minute and ampm before you query the database.
You probably need to requery the DB every cycle through the loop with the new hour, minute etc, however there is probably a more efficient way of doing this... i.e. Hit the db once for the whole days data, then use PHP to iterate out the info. 1 db call insted of 24*60*60
The below code is untested so please call me up on it if it doesn't work entirely but it should give you an idea:
$day = date('d');
$year = date('Y');
$month = date('m');
$start = mktime(0,0,0);
$thing_query="SELECT thing FROM things WHERE day='$day' AND month='$month' AND year='$year';
$result=mysql_query($thing_query);
while ($row=mysql_fetch_array($result)) {
// Loop through your hours mins etc and output desired values
}
}
All the data you need is stored in mysql_fetch_array($result) you can then loop through that where required. You dont want to be hitting the DB more than is necessary.
From what i can see you have the PHP to be able to do it - i think its a structure thing you are struggling with.

Your loop structure is wrong - you are consuming the entirety of the query result set on your first run around the parent for loop. And your internal while loop is simply setting $thing to the value of one field repeatedly, so $thing ends up being the LAST value returned from the query.
comment followup. An inefficient method of doing what you want would be:
$day = ...
$year = ...
$month = ...
$start = ...
for ($min = 0; ....) {
$hour = ...
$min = ...
$am = ...
$thing_query = "SELECT ...."
$result = mysql_query($thing_query) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
printf(.... $row[0] ... );
}
}
But this would run a query for every single time point you're checking for. Why not just store the event's date/time in a single date/time field. YOu can reduce your query to
SELECT ... WHERE timestampfield BETWEEN startdatetime AND enddatetime
then use the results of that in PHP to build up your events. A single "larger" query would be more efficient than a long series of "small" ones.

You mixed up the order of your statements pretty badly. Here's the right way, and some additional comments:
$day = date('d');
$year = date('Y');
$month = date('m');
$start = mktime(0,0,0);
for($min = 0; $min < 24 * 60 * 60; $min += 30 * 60)
{
$hour=date("h", $start + $min);
$minute=date("i", $start + $min);
$am=date("A", $start + $min);
// you must set the string after $hour/$minute/$date have the right value
$thing_query="SELECT thing FROM things WHERE day='$day' AND month='$month' AND year='$year' AND hour='$hour' AND minute='$minute' AND ampm='$am'";
// query the database with the string
$result=mysql_query($thing_query);
// put things in an array
$things = array();
while ($row=mysql_fetch_array($result)) {
$things[] = $row[0];
}
// join the array so I have a comma separated list of things
$listOfThings = implode(", ", $things);
// ALWAYS use htmlspecialchars when sending data from the database to the browser!!!!
echo "<tr><td>" . date("g:i a", $start + $min) . "</td><td>" . htmlspecialchars($listOfThings) . "</td></tr>";
}

Related

how to get sum of the total time in php

Currently i working with the attendance management system.i calculate how many hours work done in employees.i already calculate the how much hours working in day and it store in the mysql database.
$totaltime = (strtotime($time_out) - strtotime($time_in));
$hours = sprintf('%02d', intval($totaltime / 3600));
$seconds_remain = ($totaltime - ($hours * 3600));
$minutes = sprintf('%02d', intval($seconds_remain / 60));
$seconds = sprintf('%02d' ,($seconds_remain - ($minutes * 60)));
$final = '';
if ($time_in == '' || $time_out == '')
{
$final = '';
}
else
{
$final .= $hours.':'.$minutes.':'.$seconds;
}
for example
$time_in = 08:09:57
$time_out = 16:04:50
$final = 07:54:53 (total working hours)
now i want to get the current month total working time for each employee.how do get sum of the $final using php?
sample data of the month_data
Emp_no Date Time_in Time_out Total_hours TranID
23 2019-08-01 07:54:40 16:01:40 08:07:00 1
23 2019-08-02 07:42:35 16:02:53 08:20:18 2
i want get the sum of the Total_hours for related one employee
If you ask me this can be easily done using plain MySQL, no meed for PHP to calculate this.
You could take a look at a query somewhat like this
SELECT SEC_TO_TIME(SUM(`Total_hours`) ) FROM `month_data` GROUP BY `Emp_no`;
there is a simple SUM function which can do this for you, it returns the total time in seconds though.
In order to turn that into readable time you can use the MySQL function SEC_TO_TIME.
edit
If the said column is not a TIME column you can CAST it to be handled as this type of column using CAST() the needed SQL would look something like
SELECT SEC_TO_TIME(SUM(CAST(`Total_hours` AS TIME)) ) FROM `month_data` GROUP BY `Emp_no`;
My suggestion would be to change the column type to TIME though.
edit 2
I was under the assumption that SUM() would be smart enough to convert the time to seconds and come up with the correct sum of the given times.
Not sure why yet but this is not the case, therefore you need to convert the given times to seconds first.
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(`Total_hours`)) ) FROM `month_data` GROUP BY `Emp_no`;
Now I have not tested this but TIME_TO_SEC() seems to accept VARCHAR just fine so need to CAST() the column anymore.
take a look at this:
echo OverallTime($allTimes);
$allTimes = array();
function OverallTime($allTimes) {
$minutes = 0;
foreach ($allTimes as $time) {
list($hour, $minute) = explode(':', $time);
$minutes += $hour * 60;
$minutes += $minute;
}
$hours = floor($minutes / 60);
$minutes -= $hours * 60;
return sprintf('%02d:%02d', $hours, $minutes);
<?php
$total = [
'00:02:55',
'00:07:56',
'01:03:32',
'01:13:34',
'02:13:44',
'03:08:53',
'03:13:54'
];
$sum = strtotime('00:00:00');
$sum2=0;
foreach ($total as $v){
$sum1=strtotime($v)-$sum;
$sum2 = $sum2+$sum1;
}
$sum3=$sum+$sum2;
echo date("H:i:s",$sum3);
?>
In case this is useful to someone looking for this, this is what I use on my music website. This code gets the duration in seconds of all the songs in an album, adds them up, and returns the total album length in hh mm ss.
$record_id = $this->record->id; <!--variable for record-->
.$query = 'SELECT SUM(duration) FROM #__songs WHERE `record_id` = '. $db->quote( (int) $record_id ); <!--selects the duration of all the songs in the album-->
$db->setQuery($query);
$results = $db->loadResult();
echo gmdate("H:i:s", $results); <!--echo total time in hh mm ss.-->
Not an expert here. If you see something, say something XD

Build array from query for a total time calculation

I have this code that draws the data from the db, that when run displays the time totals for each record in a hh:mm format, eg 00:35 for 35 minutes.
$query="SELECT * FROM data1 ORDER BY id DESC";
$result=mysql_query ($query);
$num=mysql_num_rows ($result);
mysql_close();
$i=0;
while ($i < $num) {
$time_ttl=mysql_result($result,$i,"time_ttl");
echo $time_ttl . "<br>";
++$i;
}
The result from the query looks like this:
00:35
00:25
00:10
Total time: 01:10 (1 hour 10 minutes)
Depending on the query, the number of totals will vary, and I want to calculate a grand total depending on the query.
I tried using this code to calculate the time, which works, but I am not sure how to connect the incoming data inside the 'while { }' part:
$times = array();
$times[] = "00:35";
$times[] = "00:25";
$times[] = "00:10";
function ttl_time($times) {
foreach ($times as $time) {
list($hour, $minute) = explode(':', $time);
$minutes += $hour * 60;
$minutes += $minute;
}
$hours = floor($minutes / 60);
$minutes -= $hours * 60;
$ttl_time = sprintf('%02d:%02d', $hours, $minutes);
}
The code calculates the total time correctly, but I am looking for guidance how to build an array based on the query to feed into the ttl_time function so I can connect the incoming query data to the function.
I did try this:
$result2 = mysql_query("SELECT sum(time_ttl) FROM data1");
while ($rows = mysql_fetch_array($result2)) {
echo $rows['sum(time_ttl)'];
}
But it returns the wrong result
If I understand your question correctly...
$i=0; $result_times = array();
while ($i < $num) {
$result_times[] = mysql_result($result,$i,"time_ttl");
++$i;
}
Then you can pass $result_times to your ttl_time function.
As for your other attempted solution (using sum) it depends on the data type. This may be helpful: calculate a sum of type time using sql

How to determine if a time period is in one or more timeframes with PHP

I have some arrays of information with time periods from a database, and some predefined timeframes. Here is an example:
The predefined timeframes are: 12am-6am, 6am-9am, 9am-5pm, 5pm-8pm, 8pm-12am
My database time period might be: 4:30pm to 8:30pm.
If my database time period stretches over one or more timeframes, I need to split it into chunks. In this case I would need to split 4:30-8:30 into 4:30-5pm, 5pm-8pm, 8-8:30pm, and now have 3 arrays instead of 1. I have further operations to do to the arrays depending on the timeframe.
What I want to know is if the way I've come up with determining which timeframe(s) my arrays belong to a) makes any sense, and b) is the best way to solve the problem.
Here is a small part of my PHP, but you can see my process:
// First, a function to determine if a timeframe is between 2 dates, which I found on another SO post:
function date_between($from, $to, $date = 'now') {
$date = is_int($date) ? $date : strtotime($date);
$from = is_int($from) ? $from : strtotime($from);
$to = is_int($to) ? $to : strtotime($to);
return ($date > $from) && ($date < $to);
}
$st = $row['Start'];
$end = $row['End'];
$ot_f = date_create_from_format('M j Y H:i:s:uA', $st);
$ot_e = date_create_from_format('M j Y H:i:s:uA', $end);
$timestart = strtotime(date_format($ot_f, 'Y-m-d H:i')); //Start date, formatted
$timestop = strtotime(date_format($ot_e, 'Y-m-d H:i')); //End date, formatted
$timestump = strtotime(date_format($ot_f, 'Y-m-d')); //I take the Y-m-d from the start date, and I will append the assigned timeframes onto them
$six = $timestump + (360 * 60); //'6:00', so this becomes Y-m-d 06:00;
$nine = $timestump + (540 * 60); //'9:00'
$seventeen = $timestump + (1020 * 60); //'17:00'
$twenty = $timestump + (1200 * 60); //'20:00'
$midnite = $timestump + (1440 * 60); //'00:00'
// Start comparing here
if(date_between($six, $nine, $timestart)){ // Does the timeframe start between 6am and 9am?
if(date_between($six, $nine, $timestop)){ // Does the timeframe end between 6 and 9am?
// If so, define timeframe. It starts and ends in the same timeframe, so we only have one
$row['Start'] = $timestart;
$row['End'] = $timestop;
$row['Timeframe'] = '6-9am';
else if(date_between($nine, $seventeen, $timestop)){
// If so, split the arrays, because now we are talking about multiple timeframes
$row2 = array();
$row['Start'] = $timestart;
$row['End'] = $nine;
$row['Timeframe'] = '6-9am';
$row2['Start'] = $nine;
$row2['End'] = $timestop;
$row2['Timeframe'] = '9am-5pm';
} // Continue from here
} else if(date_between($nine, $seventeen, $timestart)){
} else if(date_between($seventeen, $twenty, $timestart)){
} else {
}
My code seems really clunky, and this is even streamlined from the first version I wrote. Am I doing this right? Could I make my code better?
Extending this answer a little more, the one main flaw I can see in this code is extendibility. If I wanted to add another time period to check I would have to add more conditional statements and more variables to do so.
If you have a set condition: does (x -> y) fall between (a -> b) and you have multiple instances of one, or both then you want to use a loop over the multiples and apply the same condition over that loop.
In this instance you have one timeperiod ($timestart, $timestop) and multiple timeframes, so you would loop over the timeframes, to see if and where your timeperiod fits.
First rather than listing out all the times as variables, I would place them in an array. This makes them loopable and it also allows you to define the start and end points of each, as opposed to writing ever increasing conditions of whether it's between $six and $nine.
I'd suggest putting the timeframes into an array something along the lines of:
$timeframes = array (
array(
"start" = "00:00",
"finish" = "06:00"
),
array(
"start" = "06:00",
"finish" = "09:00"
),
...
);
You could then use this array to perform your date_between check, each element of the array would contain the start and finish times to check as per your current function.
foreach ($timeframes as $timeframe) {
$check_start = $timeframe['start'];
$check_finish = $timeframe['finish'];
if (date_between($check_start, $check_finish, $timestart)) {
// it's a match
elseif (date_between($check_start, $check_finish, $timestop)) {
// it's a match
} else {
// it's not a match
}
}
However you could avoid doing the additional elseif by passing both the $timestart and the $timestop parameters to your date_between function.

Increment through date on week basis

I am building a php application using pgsql as its back end.
I would like to increment the date by some amount of date shich should be loaded from my database which have given value as available=1,3,5(implying monday,wednesday,friday of a week).I would like to increment these available values to current date. I am using N format in date() function to represent the values of days in a week as 1 to 7 which is stored in available field in the database
If current date =22-07-2013 which is monday,then i have to increment this to wednesday(available=3) and then to friday(available=5) And then to monday of the next week.
And so on..
but i cant do that..
i am in need of such a code where the value of available may change according to the tuples in that tuple.So i would like to increment the current date based on the value of available.
So please help me to achieve it.
The code I used is attached herewith.Please have a look at it.
<?php
$sq = "SELECT * FROM $db->db_schema.dept where active='Y' and dept_id=$dept_id";
$result = $db->query($sq);
$ftime=$result[0]['f_time'];
$ttime=$result[0]['t_time'];
$a=date('Y-m-d').$ftime;
$b=date('Y-m-d').$ttime;
$to_time = strtotime("$b");
$from_time = strtotime("$a");
$minutes= round(abs($to_time - $from_time) / 60,2). " minute";
$days=array();
$days= explode("," , $result[0]['available']);
$result[0]['available'];
$intl=$result[0]['slot_interval'];
$slots=$minutes/$intl;
$dt1 =date("m/d/Y $ftime ");
$s_mnts=explode(":",$ftime);
$m= date('N');
-- $dt=array();
$a=$dt1;
$l=0;
for($n=1;$n<=3;$n++)
{
for($k=$m;$k<=7;$k++)
{ $l=$l+1;
if(in_array($m,$days))
{
echo "dasdsa";
echo date("Y-m-d H:i:s", strtotime("$a +$l days"));
echo"<br>";
}
$m=$m+1;
if($m==7){$m=1;}
}
}
?>
where
dept_id -> primary key of the table dept
$db->query($sq); -> query is used to fetch the given values and is defined in another file named database.php in the program folder.
f_time and t_time -> fields in the table dept which describes the from_time and to_time.f_time is the time from which we have to start increment and t_time is the time to end this increment.
Please inform me whether there is any improvement in the code I have given. .
What you could do is something like this:
You say how many days you want to increment. And give an array of availables.
<?php
$inicialDate = time(); //Timestamp of the date that you are based on
$tmpDate = $inicialDate; //Copy values for tmp var
$increment = 5; //Increment five days
$available = [1,3,5]; //Days available
/*Ok, now the logic*/
while($increment > 0){
$tmpDate = strtotime("+1 day", $tmpDate); //Increase tmpdate by one day
if(in_array(date("N",$tmpDate), $available){ //If this day is one of the availables
$increment--;
}
}
$finalDate = date("m/d/Y",$tmpDate);
?>
This logic should work, although I don't know how to reproduce it via a SQL Procedure.
From what I can tell, you are after something like
UPDATE sometable
SET some_date_column = some_date_column + ('1 day'::INTERVAL * some_integer_value);

How to get mysql data from table into php date()?

Title was wierd, yes. (Im norwegian)
Okay, I'm making a counter/timer to my new project and what it do is that when a user makes a action he/she must wait 100 sec before doing it again. But, how to get the timestamp (saved in mysql db) into the PHP code again and checking how long time since last time user checked to try again.
Some of my code (From the script):
// Waiting for time to go?
$sql = mysql_query("SELECT * FROM `crimes` WHERE user_id = '".$_SESSION["id"]."'");
$num = mysql_num_rows($sql);
$row = mysql_fetch_array($sql);
if($num == 1){ //Waiting
$time_now = date("H:i:s", strtotime("+100 seconds")); // This is where Im stuck, how to get that timestamp from mysql with 100 secs added?
$time_to_check = date("H:i:s", $row["time"]); // The time the action was done.
// This is where the code is going to check how long time since user visited.
} else {
}
So what Im asking for is that I need that one var that contains the data from mysql with 100 secs added, how? :)
This works:
$sql2 = mysql_query("SELECT UNIX_TIMESTAMP(time) AS time FROM `crimes` WHERE user_id = '".$_SESSION["id"]."'");
$row2 = mysql_fetch_array($sql2);
$seconds_ago = time() - $row2['time'];
$time_now = date("H:i:s", $seconds_ago + 100);
You can convert dates to UNIX timestamps in MySQL:
SELECT UNIX_TIMESTAMP(time) AS time FROM `crimes` ...
Then inside PHP:
$seconds_ago = time() - $row['time'];
$time = date("h:i:s", time() + 100);
$time_now = strtotime("now");
$time_to_check = strtotime($row["time"]) + 100;

Categories