How to break up reports by month with php and mysql? - php

I'm trying to do something relatively simple here. Basically I have a table with a bunch of rows in it marked with a timestamp (format: 2009-05-30 00:14:57).
What I'm wanting to is do is a query which pulls out all of the rows, and splits them by the month so I'm left with a final result like:
February
rowID name order date
rowID name order date
rowID name order date
January
rowID name order date
rowID name order date
rowID name order date
etc.
I have a few vague ideas how to do this - they just seem long winded.
One of the ways would be to do a query for each month. I'd derive what the current month is in PHP then construct a for() which goes back a certain number of months.
like:
$currentmonth = 8;
$last6months = $currentmonth - 6;
for($i = $currentmonth; $i == $last6months; $i--) {
$sql = 'SELECT * FROM reports WHERE MONTH(reports.when) = $currentmonth ';
$res = mysql_query($sql);
// something would go here to convert the month numeral into a month name $currentmonthname
echo $currentmonthname;
while($row = mysql_fetch_array($res)) {
// print out the rows for this month here
}
}
Is there a better way to do this?

It's better to fetch all data once,ordered by month..
Then while fetching with php you can store your current month in a variable (for example $curMonth) and if there is a change in the month, you echo "New Month"...
Executing a query is slow, it's better to minimize your "conversations" with the db..

Don't forget that you have to deal with years aswell. If you have two records, one for January '09 and one for January '08, your results may be skewed.
Best to follow Svetlozar's advice and fetch all data at once. Once you have it in memory, use PHP to segment it into something usefull:
$monthData = array();
$queryResult = mysql_query("
SELECT
*,
DATE_FORMAT('%m-%Y', when) AS monthID
FROM
reports
WHERE
YEAR(when) = 2009 AND
MONTH(when) BETWEEN 5 and 11
");
while ($row = mysql_fetch_assoc($queryResult))
{
if (!isset($monthData[$row['monthID']]))
$monthData[$row['monthID']] = array();
$monthData[$row['monthID']][] = $row;
}
mysql_free_result($queryResult);
foreach($monthData as $monthID => $rows)
{
echo '<h2>Data for ', $monthID, '</h2>';
echo '<ul>';
foreach($rows as $row)
{
echo '<li>', $row['someColumn'], '</li>';
}
echo '</ul>';
}

You could change your SQL query to get your entire report. This is much more efficient than querying the database in a loop.
select
monthname(reports.when) as currentmonth,
other,
fields,
go,
here
from reports
order by
reports.when asc
You could then use this loop to created a nested report:
var $currentMonth = '';
while($row = mysql_fetch_array($res)) {
if($currentMonth !== $row['currentMonth']) {
$currentMonth = $row['currentMonth']);
echo('Month: ' . $currentMonth);
}
//Display report detail for month here
}
*Note: Untested, but you get the general gist of it I'm sure.

This is the SQL script:
SELECT*, DATE_FORMAT(fieldname,'%Y-%m') AS report FROM bukukecil_soval WHERE MONTH(fieldname) = 11 AND YEAR(fieldname)=2011
I hope you know where you should put this code :D

Related

How to display the serial number of the table rows in descending order in php?

I am looking way to sort the serial number of the table in descending order. I am using a here simple while loop, with a counter variable inside it.
Code sample:
$i= 0;
while(condition)
{
$i++;
echo "<td>".$i."</td>";
}
Output:
I am not using an autoincrement column here. I just want it with a simple counter, but in descending order.
example:
#
10
9
8
7
6
5
4
3
2
1
Any help is highly appreciated.
If you already have loop outputting the 1-10 version, you could simple change the output to show 11 minus the current count...
echo "<td>".(11-$i)."</td>";
Or to change the whole code, you could start at 11 and decrement the counter each time and output it that way
$i= 11;
while($i>0)
{
$i--;
echo "<td>".$i."</td>";
}
count first and after do a loop in reverse order
$i= 0;
while(condition)
{
$i++;
}
for ( cnt= $i, $i>= 0, $i--){
echo "<td>".$cnt."</td>";
}
If you are fetching from MYSQL Database and you're using PDO to connect to Database
//COUNT THE TOTAL NUMBER OF ROWS RETURNED
$sql = "SELECT COUNT(*) FROM all_tnxs ORDER BY id DESC";
$stmt = $con->query($sql);
$stmt_num_rows = $stmt->fetch();
$tot_rows = array_shift($stmt_num_rows);
$sn = $tot_rows
while(){
$sn--;
echo '<td>' . $sn . '</td>';
}
So whatever the total number of rows you have - fetching from the database it'll countdown to '0'using the while loop.
I have been looking for this for long but later figured it out myself so I decided to drop it here for anyone it might be helpful to...

multiple dates datetime

I am trying to display a table with PHP MYSQL where the FIELD is the DATE and rows are TIME from a MySQL database with unknown/infinite records, one with different TIMES for the same DATE, by querying it for the DateTime.
My mysql date stores the dateTime in the same column, but I am splitting this and trying to display them seperately. BUT I cannot seem to display the date only once and the time multiple times, it is just both.
$sql_result = mysqli_query($connection, "SELECT DATE(date_time) AS date_part, TIME(date_time) AS time_part FROM $table WHERE date_time LIKE '$date_input%'");
if (mysqli_num_rows($sql_result) == 0)
{
echo "<p>No bookings exist.</p>";
}
else {
echo "<h3>Results for booked " . $table . " Appointments:</h3>";
echo "<h3>" . $formattedDate ."</h3>";
while ($row = mysqli_fetch_array($sql_result))
{
echo $row['date_part'];
$array_time = array($row['time_part']);
foreach ($array_time as $time_output)
{
echo $time_output;
}
}
}
My output is like this:
2013-12-0809:00:002013-12-0810:00:002013-12-0811:00:002013-12-0812:00:002013-12-0814:00:002013-12-0815:00:002013-12-0816:00:002013-12-0817:00:002013-12-0909:00:002013-12-0809:00:00
But I would like it like this:
2013-12-08 09:00:0010:00:0011:00:0012:00:0014:00:0015:00:0016:00:0017:00:0009:00:000
2013-12-09 9:00:00
Hrrmm. Theres a bit of logic problem here:
while ($row = mysqli_fetch_array($sql_result))
{
echo $row['date_part'];
$array_time = array($row['time_part']); // HERE
foreach ($array_time as $time_output)
{
echo $row['time_part'];
}
}
$array_time will always have only one value, since $row['time_part'] only refers to ONE row (each iteration of while ($row = mysqli_fetch_array($sql_result)) reassigns a single row to $row)
try doing this first pass to define a workable array
while ($row = mysqli_fetch_array($sql_result))
{
$array[$row['date_part']][$row['time_part']] = 1; // the value assigned doesn't matter, all we wish is a definite hierarchy
}
this will give you an array like:
['2013-12-08']['9:08'] = 1
['12:30'] = 1
[23:17] = 1
['2013-12-09']['10:00'] = 1
[14:20] = 1
THEN! you can foreach through your result
foreach ($array as $date_part => $array_time)
{
echo $date_part . ' ';
foreach ($array_time as $time_part => $i) // again our $i is not used
{
echo $time_part;
}
echo '<br>'; // here it breaks line after all times for the date has been echoed
}
You need to GROUP in your query:
SELECT DATE(date_time) AS date_part, TIME(date_time) AS time_part
FROM $table
WHERE date_time LIKE '$date_input%'
GROUP BY date_part
I think I understand what you're trying to say, however, MySQL won't create a multidimensional array. You should try something like this:
$dates = array();
while ($row = mysqli_fetch_array($sql_result)) {
$dates[$row['date_part']][] = $row['time_part']
}
Then you could have something like this:
foreach ($dates as $key => $value) {
echo $key.'<br />';
foreach ($value as $time) {
echo $time.' - ';
}
echo '<br />';
}
which should look something like:
2013-09-01
09:00 - 09:30 - 10:20 - 11:00
2013-09-02
10:12 - 11:00 - 12:24 //etc
Hope this helps!
Two comments. First, it seems like you need an order by time so as to order your records.
SELECT DATE(date_time) AS `date_part`, TIME(date_time) AS `time_part`
FROM $table
WHERE date_time LIKE '$date_input%'
ORDER BY date_time ASC
Second, if I read your question correctly, it seems like you want to output your data into two columns, one with date and the other with all times for that date. You might consider using GROUP_CONCAT() to do this in SQL, making your output easy.
SELECT DATE(date_time) AS `date_part`, GROUP_CONCAT(TIME(date_time)) AS `times`
FROM $table
WHERE date_time LIKE '$date_input%'
GROUP BY `date_part`
ORDER BY date_time ASC
This would give output like
date_part times
2013-12-08 11:22:33,11:33:44,12:44:55
2013-12-09 12:00:00
With this approach, there would be no need to build a multi-dimensional array in PHP, as the data would come out of the database just the way you need it. That also means that you don't need to load the entire result set into memory in order to work with it (as you would have to do if creating multi-dimensional array).

calendar with sql

PHP+SQL question:
I have table for assignments
one of the field is "progTargetDate" -> linux time (eg: 1348185600 )
I also built calender and I want to check if I have any assignment for each day I print
so - I wrote the query that bring me all the assignment for the current month
$query = mysql_query("SELECT ass.id, ass.title, ass.des, ass.progTargetDate
FROM pro_assignments AS ass, pro_progs2assignments AS pr
WHERE (ass.progTargetDate >= $ChoosenMonth_start) AND
(ass.progTargetDate <= $ChoosenMonth_end)
ORDER BY ass.progTargetDate ASC
");
(I delete part of the SQL query))
and I have the loop that build the calendar cell
for ($i = 1 ; $i <= $total_days_in_month ; $i++)
{
}
$i = each day in the month
I tried to build IF condition without success
I want to check for each day if it found inside the array (that I got from the first query)
(this code goes inside the FOR loop:)
echo "<td>$i";
while($index = mysql_fetch_array($query))
{
$progTargetDate = $index['progTargetDate'];
if ((mktime(0, 0, 0, date($ChoosenMonth) , $i, date($ChoosenYear)) == $progTargetDate))
echo "<p>found</p>";
else
echo "<p>not</p>";
}
echo "</td>";
What do I do wrong?
for 31 days I should have 31 cell with "found" or "not" in each one. but for some reason only in the first cell I see this result

Making an array out of variables and update its contents based on one of the variables

I have a question that pertains to gathering events from tables in a calendar program where they are separated into "events" or "repeated events". I can get all individual events perfectly well now (thanks to Chris on this site), but if they are repeating events I have to calculate it from what is given in this particular db. If I change the types or the data in the db, it will probably trash the calendar so I have to use what I have.
The variables I have sorted out so far are:
$quid2 = The IDs for today's events that are classified as repeating events (needed earlier)
$quname = The repeated event names
$qucls = The date UNIX time for the last sent reminder of events dated today
$qutype = One of these words - daily, weekly, monthly or yearly
$qudesc = A description of the event
These variables all have the same number of items and are ordered correctly between each other. (I Hope)
Below is the logic I am trying to accomplish. It are most assuredly not proper syntax but I think it is understandable; I need to figure out what the syntax and form is. I am utterly and completely new at this... so please be gentle...
It needs to be put in an array (I think)
$arr1 = some type of array($quname, $qucls, $qutype, $qudesc)
update the array...
IF $qutype($row2) = "daily", then + 1440 to it's $qucls($row[1])
IF $qutype($row2) = "weekly", then + 10080 to it's $qucls($row[1])
IF $qutype($row2) = "monthly, then + 1 month to it's $qucls($row[1])
IF $qutype($row2) = "yearly", then + 1 year to it's $qucls($row[1])
Then final product...
while ($row = mysql_fetch_array($arr1, MYSQL_NUM)) {
$UxTime = $row[1];
date_default_timezone_set('America/Denver');
$Time = date("H:i", $UxTime);
$qufinal = sprintf("Event: %s \nTime: %s \nDesc: %s \n\n", $row[0], $Time, $row[3);
}
...
This is a big learning project for me. I don't know enough PHP and mysql to make this work but I know just enough to get me in trouble. Thanks!
EDIT: adding the queries from which I made these variables:
$today = date("Ymd");
mysql_select_db($dbname);
$query1 = "SELECT cal_id, cal_name, cal_date, cal_time, cal_type, cal_description FROM webcal_entry WHERE cal_type = "M" AND cal_date != " . $today;
$wequ1 = mysql_query($query1)
while ($row = mysql_fetch_array($wequ1, MYSQL_NUM)) {
$quid1 = $row[0], $quname = $row[1], $qutime = $row[2], $qudesc = $row[3];
}
$query2 = "SELECT cal_id, cal_type, cal_ByDay FROM webcal_entry_repeats WHERE cal_id = " . $quid1;
$wer1 = mysql_query($query2)
while ($row = mysql_fetch_array($wer1, MYSQL_NUM)) {
$quid2 = $row[0] $qutype = $row[1], $qubdy = $row[2];
}
$query3 = "SELECT cal_id, cal_last_sent FROM webcal_reminders WHERE cal_id = " . $quid2;
$wer2 = mysql_query($query3)
while ($row = mysql_fetch_array($wer2, MYSQL_NUM)) {
$qucls = $row[1];
}
The syntax for arrays is as follows:
$arrayName = array($quname, $qucls, $qutype, $qudesc);
Then you can access the values by their index on the array variable:
$arrayName[0] == $quname
$arrayName[1] == $qucls
...
You can also define it as associative array:
$arrayName = array(
"quname" => $quname,
"qucls" => $qucls,
"qutype" => $qutype,
"qudesc" => $qudesc
);
Using this syntax you can access the elements by their name:
$arrayName["quname"] == $quname
$arrayName["qucls"] == $qucls
...
More reading on this: Arrays
However, you don't really need an array for what you plan to do here. Arrays are very useful if you want to store data that is structurally equal. This applies e.g. to rows in a database: They always have the same number of entries, and the columns are of the same type.
If you have just one dataset at that point of code (one event in this case), then you need no array. Of course you have several events, but as they are processed in a loop (I assume) you handle only one event at a time, and then head to the next.
So, you want to modify a variable depending on the value $qutype. To do that, you can use a switch statement:
$dateObj = date_create("#$qucls");
switch($qutype) {
case "daily":
date_add($dateObj, date_interval_create_from_date_string("1 day"));
break;
case "weekly":
date_add($dateObj, date_interval_create_from_date_string("1 week"));
break;
case "monthly":
date_add($dateObj, date_interval_create_from_date_string("1 month"));
break;
case "yearly":
date_add($dateObj, date_interval_create_from_date_string("1 year"));
break;
}
$qucls = date_format($dateObj, "U");
I don't add the number of seconds, because that would work for days and weeks- but not for months and years, as they don't have a fixed number of seconds.
If you have questions about the functions I used above you can look up their documentation on php.net.
In the code you show you must not use mysql_fetch_array.
That function is only meant for result rows you got from a call to mysql_query, but not for normal arrays.
You don't need the while loop either. All you have to do is formatting $qucls to a readable format and produce the final string:
date_default_timezone_set('America/Denver');
$Time = date("H:i", $qucls);
$qufinal = sprintf("Event: %s \nTime: %s \nDesc: %s \n\n", $quname, $Time, $qudesc);
Edit:
Like discussed in the comments here is the revised and commented code you edited in:
$today = date("Ymd");
mysql_select_db($dbname);
// You need to use single quotes at the 'M'. Using double quotes will
// end the string and thus leading to incorrect syntax
$query1 = "SELECT cal_id, cal_name, cal_date, cal_time, cal_type, cal_description FROM webcal_entry WHERE cal_type = 'M' AND cal_date != " . $today;
$wequ1 = mysql_query($query1);
// This is a counter variable which is incremented in the loop
$i = 0;
// This is the outer while loop used to gather and store the events
while ($row = mysql_fetch_array($wequ1, MYSQL_NUM)) {
// Store the results in arrays
// Statements must be seperated by a ;
$quid1[$i] = $row[0];
$quname[$i] = $row[1];
$qutime[$i] = $row[2];
$qudesc[$i] = $row[3];
$query2 = "SELECT cal_id, cal_type, cal_ByDay FROM webcal_entry_repeats WHERE cal_id = " . $quid1[$i];
$wer1 = mysql_query($query2);
// Assuming that IDs are unique this query can only return one entry. Therefore no while is
// needed, but an if statement tests if the ID actually matched a result
if ($row = mysql_fetch_array($wer1, MYSQL_NUM)) {
//$quid2[$i] = $row[0]; <- the query above ensures that $quid1[$i] == $quid2[$i]. No need to store it again
$qutype[$i] = $row[1];
$qubdy[$i] = $row[2];
}
$query3 = "SELECT cal_id, cal_last_sent FROM webcal_reminders WHERE cal_id = " . $quid1[$i];
$wer2 = mysql_query($query3);
// Same as above; If the IDs are unique then you need no loop
if ($row = mysql_fetch_array($wer2, MYSQL_NUM)) {
// The $i++ used here is the short form. As this is the last time $i is
// used in the loop it needs to be increased before the next round. You can do
// this like this or in an extra statement. This way it's evaluated and then increased
$qucls[$i++] = $row[1];
}
// End outer while loop
}
// Now go through the results. $i holds the number of entries in the arrays + 1
// Secondary counter variable and for-loop
for ($j = 0; $j < $i; $j++) {
// Adding the dates to $qucls, formatting the string, ...
// Access them like above: $qucls[$j]
// Do not increase $j manually though - the for loop does that for you already
}
Please note that this code is untested. It's syntactically correct though.
On a side note: You are currently using three different database queries to gather the data.
You can easily merge them into a single query using SQL JOINs. If you want somebody to show you how to do that, you can show them in a seperate question and ask for them to be joined into one.

Dynamic X-axis graph that will change according to the count of rows

Let's say I have a mysql table with an id, some measurements and a DATE column.
Example: id, measurements, date_entered
This table stores some measurements of a patient so as to keep a record for him.
I want to make a graph which according to the count of rows that exist in the database will change dynamically the X-axis.
For example, if there are only 7 rows in the table I need to represent 7 days to the graph with the measurement for every day. If there are more than 14 days, I want it to change to respresent 2 weeks on X-axis and the average measurements(average for 1 week and average for the other too) on Y-axis and so on from weeks to months.
Can anyone help me on this? I cannot think of something that will do in my case..
I use JPGraph to make the line graph but i don't have a problem there. My problem is on how to handle the results.
I hope you will understand what I need! Thanks.
Something like this?
// Get the results from the database
$query = "SELECT `data_col` FROM `table` WHERE `condition_col` = 'some value'";
$result = mysql_query($query);
// Get all results into array and count them
$results = array();
for ($i = 0; $row = mysql_fetch_assoc($result); $i++) {
$results[] = $row;
}
// Re-format the data depending on number of results
$data = array();
if ($i < 14) { // Less than 14 days, show per day
foreach ($results as $row) {
$data[] = $row['data_col'];
}
} else if ($i < 56) { // Less than 8 weeks, show per-week
$thisweek = array();
for ($j = 0; isset($results[$j]); $j++) { // Loop the results
$thisweek[] = $results[$j]['data_col']; // Add result to this week total
if ($j % 7 == 0 && $j > 0) { // Every 7 days...
$data[] = array_sum($thisweek) / 7; // ...calculate the week average...
$thisweek = array(); // ...and reset the total
}
}
// If there is an incomplete week, add it to the data
$data[] = array_sum($thisweek) / count($thisweek);
} else { // 8 weeks or more, show per-month
$thismonth = array();
for ($j = 0; isset($results[$j]); $j++) { // Loop the results
$thismonth[] = $results[$j]['data_col']; // Add result to this month total
if ($j % 28 == 0 && $j > 0) { // Every 28 days...
$data[] = array_sum($thismonth) / 28; // ...calculate the month average...
$thismonth = array(); // ...and reset the total
}
}
// If there is an incomplete month, add it to the data
$data[] = array_sum($thismonth) / count($thismonth);
}
// $data now contains an array from which you should be able to draw your
// graph, where array keys are (sort of) x values and array values are y
// values.
Obviously, this solution assumes a 28-day month - it does not use the calendar, simply the number of days. You could do something horrible involving working out the stats based on some values returned by date() or similar, but this would likely drastically increase the calculation overhead and slow the process down.
Hopefully this will give you a place to start.

Categories