MySQL - Group and summarize time entries on projects - php

I've got these timerecording data from toggl.com where I need to have my reports formatted a bit different than what they supply - that's why I thought I'd try to import the csv data to MySQL and group and format it myself via MySQL and PHP etc. but I'm stuck almost before I started - got the data into MySQL, so now I need to output it in a html table... somehow.
I've got these data:
+-----------+---------------------------------------+------------+----------+
| Project | Task name | Date | Duration |
+-----------+---------------------------------------+------------+----------+
| Project 1 | Task name 2 | 2016-05-12 | 00:22:03 |
| Project 2 | Task name 1 | 2016-05-12 | 00:04:24 |
| Project 2 | Task name 1 | 2016-05-12 | 00:06:27 |
| Project 1 | 3. correction | 2016-05-13 | 00:08:00 |
| Project 1 | Small correction | 2016-05-13 | 00:02:02 |
| Project 1 | Last correction | 2016-05-16 | 00:05:36 |
| Project 1 | Created low-res | 2016-05-16 | 00:04:21 |
| Project 2 | Layout | 2016-05-24 | 00:27:45 |
| Project 2 | Layout | 2016-05-25 | 01:00:00 |
| Project 2 | Finishing | 2016-05-25 | 00:15:48 |
+-----------+---------------------------------------+------------+----------+
What I dream to achieve is data for each project that looks like this:
Project 2
-----------------------------------------------------
Date Tasks Total
-----------------------------------------------------
12/05/16 Task name 1 00:10:51
24/05/16 Layout 00:27:45
25/05/16 Layout, Finishing 01:15:48
-----------------------------------------------------
Project 2 total 01:54:24
So for each Project, each Date should have its own row, including Date, Task names (comma delimited) and the sum of the Duration for that Date
And then a project total.
Any help would be very appreciated!! :-)
EDIT:
SELECT
Project,
`Task name`,
Date,
Duration,
SEC_TO_TIME( SUM( TIME_TO_SEC( `Duration` ) ) ) AS TotalDuration
FROM timerecordings
GROUP BY Project, Date, `Task name` WITH ROLLUP
Gives me (don't look at the date and time formating, it's excel that does it):
+-----------+------------------+------------+----------+----------+
| Project 1 | Task name 2 | 12/05/2016 | 00.22.03 | 00.22.03 |
| Project 1 | NULL | 12/05/2016 | 00.22.03 | 00.22.03 |
| Project 1 | 3. correction | 13/05/2016 | 00.08.00 | 00.08.00 |
| Project 1 | Small correction | 13/05/2016 | 00.02.02 | 00.02.02 |
| Project 1 | NULL | 13/05/2016 | 00.02.02 | 00.10.02 |
| Project 1 | Created low-res | 16/05/2016 | 00.04.21 | 00.04.21 |
| Project 1 | Last correction | 16/05/2016 | 00.05.36 | 00.05.36 |
| Project 1 | NULL | 16/05/2016 | 00.05.36 | 00.09.57 |
| Project 1 | NULL | NULL | 00.05.36 | 00.42.02 |
| Project 2 | Task name 1 | 12/05/2016 | 00.04.24 | 00.10.51 |
| Project 2 | NULL | 12/05/2016 | 00.04.24 | 00.10.51 |
| Project 2 | Layout | 24/05/2016 | 00.27.45 | 00.27.45 |
| Project 2 | NULL | 24/05/2016 | 00.27.45 | 00.27.45 |
| Project 2 | Finishing | 25/05/2016 | 00.15.48 | 00.15.48 |
| Project 2 | Layout | 25/05/2016 | 01.00.00 | 01.00.00 |
| Project 2 | NULL | 25/05/2016 | 01.00.00 | 01.15.48 |
| Project 2 | NULL | NULL | 01.00.00 | 01.54.24 |
| NULL | NULL | NULL | 01.00.00 | 02.36.26 |
+-----------+------------------+------------+----------+----------+

You can use GROUP_CONCAT aggregate function to combine all task names in one string. Use SEPARATOR keyword to define the separator (default: ','). Use DISTINCT if you don't want same task to be listed multiple times.
For one project:
SELECT Date,
GROUP_CONCAT(DISTINCT `Task name` SEPARATOR ', ') AS Task,
SEC_TO_TIME(SUM(TIME_TO_SEC(Duration))) AS Total
FROM timerecordings r
WHERE Project = 'Project 2'
GROUP BY Date WITH ROLLUP;
For all projects:
SELECT SELECT Project, Date,
GROUP_CONCAT(DISTINCT `Task name` SEPARATOR ', ') AS Task,
SEC_TO_TIME(SUM(TIME_TO_SEC(Duration))) AS Total
FROM timerecordings r
GROUP BY Project, Date WITH ROLLUP;
sqlfiddle

Must be something like
select date, taskName, sum(duration) from tasksTable where Project = "Project 2" group by date
But how will the times be added, and how will you get all the taskNames in one field is still to be experimented.

So just to let you have my final result:
<?php
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "timerecordings";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT
IFNULL (Project,'All Projects') Project,
IFNULL (Date,'Project total') Date,
GROUP_CONCAT(DISTINCT `Task name` SEPARATOR ', ') AS Task,
SEC_TO_TIME(SUM(TIME_TO_SEC(Duration))) AS Total
FROM timerecordingstable r
GROUP BY Project, Date WITH ROLLUP;
";
$result = $conn->query($sql);
$data = array();
while($row = $result->fetch_assoc()) {
$projectname = $row["Project"];
if (!array_key_exists($projectname, $data)) {
$data[$projectname] = array();
}
$data[$projectname][] = $row;
}
foreach ($data as $projectname => $rows) {
if($projectname != 'All Projects'){
echo '<h1>', $projectname, '</h1>';
echo '<table class="time-table"><tr class="table-header"><th>Date</th><th>Tasks</th><th>Time used</th><tr>';
foreach ($rows as $row) {
//Convert Total into seconds
$str_time = $row["Total"];
$str_time = preg_replace("/^([\d]{1,2})\:([\d]{2})$/", "00:$1:$2", $str_time);
sscanf($str_time, "%d:%d:%d", $hours, $minutes, $seconds);
$time_seconds = $hours * 3600 + $minutes * 60 + $seconds;
// Round to nearest minute
$time_seconds = round($time_seconds/60)* 60;
$hours = floor($time_seconds / 3600); //Hours
$minutes = floor(($time_seconds / 60) % 60); //Minutes
//Convert minutes to two decimal number (like 15 minutes = 0.25 hour etc.)
$minutes = $minutes / 60;
$minutes = round($minutes,2);
$minutes = $minutes*100;
$seconds = $time_seconds % 60; //Seconds - I don't use it but kept to show it's possible
//Loop each row
if($row["Date"] == 'Project total'){
echo '<tr class="table-footer"><td>', $row["Date"] , '</td><td>' , ' ' , '</td><td>' , $hours, ',',$minutes, ' hour(s)</td></tr>';
} else {
$prettyDate = DateTime::createFromFormat('Y-m-j', $row["Date"]);
echo '<tr><td>', $prettyDate->format('d-m-Y') , ':</td><td>' , $row["Task"] , '</td><td>' , $hours, ',',$minutes, ' hour(s)</td></tr>';
}
}
echo '</table>';
}
}
$conn->close();
?>
Results:
<h1>Project 1</h1>
<table class="time-table">
<tr class="table-header">
<th>Date</th>
<th>Tasks</th>
<th>Time used</th>
<tr>
<tr>
<td>12-05-2016:</td>
<td>Task name 2</td>
<td>0,37 hour(s)</td>
</tr>
<tr>
<td>13-05-2016:</td>
<td>3. correction, Small correction</td>
<td>0,17 hour(s)</td>
</tr>
<tr>
<td>16-05-2016:</td>
<td>Last correction, Created low-res</td>
<td>0,17 hour(s)</td>
</tr>
<tr class="table-footer">
<td>Project total</td>
<td> </td>
<td>0,70 hour(s)</td>
</tr>
</table>
<h1>Project 2</h1>
<table class="time-table">
<tr class="table-header">
<th>Date</th>
<th>Tasks</th>
<th>Time used</th>
<tr>
<tr>
<td>12-05-2016:</td>
<td>Task name 1</td>
<td>0,18 hour(s)</td>
</tr>
<tr>
<td>24-05-2016:</td>
<td>Layout</td>
<td>0,47 hour(s)</td>
</tr>
<tr>
<td>25-05-2016:</td>
<td>Layout, Finishing</td>
<td>101,27 hour(s)</td>
</tr>
<tr class="table-footer">
<td>Project total</td>
<td> </td>
<td>101,90 hour(s)</td>
</tr>
</table>

Related

How to do a calculation with a column in database and insert the result Codeigniter

Basically i have to count the monthly meal allowance for each of the employee based on their monthly attendance, which only leave me with just one table, attendance table
The calculation for the meal allowance is pretty simple, i only need to count how many days the employee attended and calculate it with one number (this number should be dynamic or editable)
this is the example of the calculation:
number of attendance * 15.00 (editable number)
here's my data for attendance table
----------------------------------------------------------------------------
| attendance_id | emp_code | emp_name | date | time_in | time_out |
| 1 | ALB | Albert | 2018.01.01 | 07.00 | 18.00 |
| 2 | GlN | GLENN | 2018.01.01 | 07.00 | 18.00 |
| 3 | ALB | Albert | 2018.01.02 | 07.00 | 18.00 |
| 4 | GLN | GLENN | 2018.01.02 | 07.00 | 18.00 |
| 5 | ALB | Albert | 2018.01.04 | 07.00 | 18.00 |
| 6 | GLN | GLENN | 2018.01.04 | 07.00 | 18.00 |
----------------------------------------------------------------------------
So far i already managed to count the monthly recap (by counting how many days they attended), this is my current condition:
------------------------------------------------
| emp_code | emp_name | days_attended |
| ALB | Albert | 3 |
| GLN | GLENN | 3 |
-------------------------------------------------
This is my controller
public function index(){
$this->load->model('allowance_m');
$data['query'] = $this->allowance_m->calculate();
$this->load->vars($data);
$this->load->view('allowance_v',$data);
}
This is my model (allowance_m.php)
public function hitungabsen()
{
$this->db->select('attendance_id,emp_code,emp_name, COUNT(date) as days_attended');
$this->db->from('attendance');
$this->db->group_by('emp_code');
$query = $this->db->get();
return $query->result();
}
This is my view allowance_v.php
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th><center>Employee Code</center></th>
<th><center>Employee Name</center></th>
<th><center>Days Attended</center></th>
</tr>
</thead>
<?php
$no = 1;
foreach($query as $row){
?>
<tr>
<td><?php echo $row->emp_code ?></td>
<td><?php echo $row->emp_name ?></td>
<td><?php echo $row->days_attended ?></td>
</tr>
<?php } ?>
</table>
Now i really need to know how can i calculate the meal allowance with the inputted days attended, and after calculating the result, i need to insert the result into the database so that i can make a pdf report about that. the result should be like this:
------------------------------------------------------------------------
| emp_code | emp_name | days_attended | meal allowance |
| ALB | Albert | 3 |(automaticaly updated) |
| GLN | GLENN | 3 |(automaticaly updated) |
------------------------------------------------------------------------
THANK YOU IN ADVANCE! Really need the answer as soon as possible, it means a lot for me
Don't really understand everything but this should work:
public function calc() {
$meal_allowance = array_column($this->db->select('emp_code')->get('tablename')->result_array(), 'emp_code');
$n = 15;
$results = $this->hitungabsen();
$this->db->trans_start();
foreach ($results as $row) {
$calc = intval($row->days_attended) * $n;
if (in_array($row->emp_code, $meal_allowance)) {
$this->db->update('tablename', array('meal_allowance' => $calc));
} else {
$data = array(
'emp_code' => $row->emp_code,
'emp_name' => $row->emp_name,
'days_attended' => $row->days_attended,
'meal_allowance' => $calc
);
$this->db->insert('tablename', $data);
}
}
$this->db->trans_complete();
return $this->db->trans_status();
}
Updates if a record exists, inserts if it doesn't (assumed separate table with the specs in your last graph)

Putting more than one MySQL Row in a column

the problem that i've is, that I have a Table in my Database and want to fetch some of the rows of this table in one column.
For example I've this table names klz:
|-------+-----------+-----+-----|
| ID | Name | LNr | LID |
|-------+-----------+-----+-----|
| 1 | 0000_01 | 1 | 16 |
| 2 | 0000_01 | 2 | 35 |
| 3 | 0000_02 | 1 | 16 |
| 4 | 0000_02 | 2 | 35 |
| 5 | 0000_10 | 1 | 18 |
| .. | .. | .. | .. |
| 297 | 0214_01 | 1 | 23 |
| 298 | 0214_01 | 1 | 66 |
| 299 | 0214_01 | 2 | 24 |
| 300 | 0214_01 | 2 | 67 |
| 301 | 0214_01 | 3 | 26 |
| 302 | 0214_01 | 4 | 28 |
| 303 | 0214_01 | 4 | 69 |
| 304 | 0214_01 | 5 | 30 |
| 305 | 0214_01 | 5 | 70 |
| 306 | 0214_01 | 6 | 31 |
| 307 | 0214_01 | 6 | 71 |
|-------+-----------+-----+-----|
If I fetch this table with a while-loop in PHP I would get the same table.
So what I want to have is a table like this:
|-----------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------|
| Name | LNr1 | LNr2 | LNr3 | LNr4 | LNr5 | LNr6 | LNr7 | LNr8 | LNr9 | LNr10 |
|-----------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------|
| 0000_01 | 16 | 35 | | | | | | | | |
| 0000_02 | 16 | 35 | | | | | | | | |
| 0000_10 | 18 | | | | | | | | | |
| 0214_01 | 23 - 66 | 24 | 26 - 68 | 28 - 69 | 30 - 70 | 31 - 71 | | | | |
|-----------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------|
This table have the column Name and an enumeration of the possible LNr from 1 to 10 as columns. The data inside the LNr columns arethe LIDs from the table above.
My Question is, how can I put in dependency of the Name and the LNr, the LIDs in the right columns?
In this table you have listed all Names once and set for all LNr the right LID.
Here is the Code I'm trying to do this with... Until now it works only for the first LNr column, to write the LID in:
<?php
include "dbconnect.php";
$klz = mysqli_query($db, "SELECT *
FROM klz;");
?>
<div class="container-fluid">
<div class="row">
<div class="table-responsive">
<div class="col-xs-12">
<table id="grid-klz" class="table table-condensed table-hover table-striped">
<thead>
<tr>
<th> Name </th>
<th> Leitungsnr 1</th>
<th> Leitungsnr 2</th>
<th> Leitungsnr 3</th>
<th> Leitungsnr 4</th>
<th> Leitungsnr 5</th>
<th> Leitungsnr 6</th>
<th> Leitungsnr 7</th>
<th> Leitungsnr 8</th>
<th> Leitungsnr 9</th>
<th> Leitungsnr 10</th>
</tr>
</thead>
<tbody>
<?php
$name_old = "";
$lnr_old = "";
$name = [];
$lnr = [];
$lid = [];
while($row = mysqli_fetch_array($klz, MYSQL_ASSOC)){
$name[] = $row['Name'];
$lnr[] = $row['LNr'];
$lid[] = $row['LID'];
}
for($i=0; $i <= sizeof($name)-1; $i++){
if($name[$i] != $name_old){
echo "<tr>";
echo "<td>". $name[$i] . "</td> \n";
if($lnr[$i] != $lnr_old){
echo "<td>". $lid[$i] . "</td> \n";
$lnr_old != $lnr[$i];
}
echo "</tr>";
$name_old = $name[$i];
}
}
?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php
mysqli_close($db);
?>
I hope you know what I mean and trying to do. If not feel free to ask please.
Thank you
Start with this query
SELECT
Name AS tableRows,
LNr AS tableCols,
GROUP_CONCAT(LID ORDER BY LID SEPARATOR ' - ') AS cellValue
FROM klz
GROUP BY 1,2
ORDER BY 1,2;
Now put the results in an array.
Also, get every distinct column (LNr) and row (Name) in other arrays.
$ar = array();
$tableRows = array();
$tableCols = array();
while($row = mysqli_fetch_array($klz, MYSQL_ASSOC)){
$ar[$row['tableRows']][$row['tableCols']] = $row['cellValue'];
$tableRows[] = $row['tableRows'];
$tableCols[] = $row['tableCols'];
}
$tableRows = array_unique($tableRows);
$tableCols = array_unique($tableCols);
sort the 2 arrays with rows and columns
sort($tableRows);
sort($tableCols);
foreach row, foreach column, echo value of the multi array
echo "<table>";
echo "<tr><th>Name</th>";
foreach($tableCols as $x){
echo "<th>LNr$x</th>";
}
echo "</tr>";
foreach($tableRows as $y){
echo "<tr><td>$y</td>";
foreach($tableCols as $x){
echo "<td>" . $ar[$y][$x] . "</td>";
}
echo "</tr>";
}
echo "</table>";
I'm not certain I understand correctly, but I think this query should be very close to what you're trying to do:
select name,
max(LNr1) as LNr1,
max(LNr2) as LNr2,
...
max(LNr10) as LNr10
from
(
select name,
if(LNr = 1, LID, null) as LNr1,
if(LNr = 2, LID, null) as LNr2,
...
if(LNr = 10, LID, null) as LNr10
from klz
) res
group by name
The inner part will split your rows in different "LNr" columns and give you what I like to call a "stairway" resultset. All we have to do now is flatten it, which is what the outer query does by selecting max(LNr) for each row and grouping by name. It works because by default an actual value is always bigger than null, so selecting the max for each column will get rid of the null values and give you the actual value.
You can write query like this
SELECT a.name,
GROUP_CONCAT(LNr1.LID SEPARATOR '-') AS LNr1,
GROUP_CONCAT(LNr2.LID SEPARATOR '-') AS LNr2,
GROUP_CONCAT(LNr3.LID SEPARATOR '-') AS LNr3,
GROUP_CONCAT(LNr4.LID SEPARATOR '-') AS LNr4,
GROUP_CONCAT(LNr5.LID SEPARATOR '-') AS LNr5,
GROUP_CONCAT(LNr6.LID SEPARATOR '-') AS LNr6,
GROUP_CONCAT(LNr7.LID SEPARATOR '-') AS LNr7,
GROUP_CONCAT(LNr8.LID SEPARATOR '-') AS LNr8,
GROUP_CONCAT(LNr9.LID SEPARATOR '-') AS LNr9,
GROUP_CONCAT(LNr10.LID SEPARATOR '-') AS LNr10
FROM klz AS a
LEFT JOIN klz AS LNr1 ON LNr1.LNr = 1 AND a.id = LNr1.id
LEFT JOIN klz AS LNr2 ON LNr2.LNr = 2 AND a.id = LNr2.id
LEFT JOIN klz AS LNr3 ON LNr3.LNr = 3 AND a.id = LNr3.id
LEFT JOIN klz AS LNr4 ON LNr4.LNr = 4 AND a.id = LNr4.id
LEFT JOIN klz AS LNr5 ON LNr5.LNr = 5 AND a.id = LNr5.id
LEFT JOIN klz AS LNr6 ON LNr6.LNr = 6 AND a.id = LNr6.id
LEFT JOIN klz AS LNr7 ON LNr7.LNr = 7 AND a.id = LNr7.id
LEFT JOIN klz AS LNr8 ON LNr8.LNr = 8 AND a.id = LNr8.id
LEFT JOIN klz AS LNr9 ON LNr9.LNr = 9 AND a.id = LNr9.id
LEFT JOIN klz AS LNr10 ON LNr10.LNr = 10 AND a.id = LNr10.id
GROUP BY a.name;
Hope this helps.

Issue with Group by in PHP

My database design : http://i.stack.imgur.com/3Rm2e.png
I am trying to use below code :
$myselect = mysql_query("
SELECT
reason.ReasonName,
tblexam.EXAMDATE,
tblexam.EXAMTIME,
prefix.PREFIXABB,
studentmaster.STUDENTNAME,
studentmaster.STUDENTSURNAME,
studentmaster.STUDENTCODE,
program.PROGRAMNAME,
course.COURSENAMEENG
FROM
reason,
formlate,
tblexam,
studentmaster,
prefix,
program,
course
WHERE
reason.ReasonID = formlate.ReasonID AND
formlate.CLASSID = tblexam.CLASSID AND
formlate.COURSEID = formlate.COURSEID AND
formlate.ROOMID = formlate.ROOMID AND
prefix.PREFIXID = studentmaster.PREFIXID AND
formlate.STUDENTID = studentmaster.STUDENTID AND
program.PROGRAMID = studentmaster.PROGRAMID AND
course.COURSEID = tblexam.COURSEID
GROUP BY
reason.ReasonID,studentmaster.STUDENTID
ORDER BY
reason.ReasonID ASC");
<body>
<?php $i =1;
while($rowfet = mysql_fetch_array($myselect)){
?>
<h2><?php echo $rowfet['ReasonName']; ?></h2>
<h3><?php echo DateThai($rowfet['EXAMDATE']) . ' ' . MorningEvening($rowfet['EXAMTIME']); ?></h3>
<table width="100%" border="1">
<thead>
<tr>
<th>No.</th>
<th>studentid </th>
<th>Fullname </th>
<th>Program </th>
<th>Coursename </th>
</tr>
</thead>
<tbody>
<tr>
<td align="center"><?php echo $i; ?></td>
<td><?php echo $rowfet['STUDENTCODE']; ?></td>
<td><?php echo $rowfet['PREFIXABB'] . $rowfet['STUDENTNAME'] . ' '.$rowfet['STUDENTSURNAME']; ?></td>
<td><?php echo $rowfet['PROGRAMNAME']; ?></td>
<td><?php echo $rowfet['COURSENAMEENG']; ?></td>
</tr>
</tbody>
</table>
<?php $i++; } ?>
but it shows the result like :
Reason1
10 Jan 2015 (Morning)
| No | studentid | Fullname | Program | Coursename |
-------------------------------------------------------
| 1 | 111111 | John | ProgA | Math |
---------------------------------------------------------
Reason1
10 Jan 2015 (Morning)
| No | studentid | Fullname | Program | Coursename |
-------------------------------------------------------
| 2 | 2222222 | Jane | ProgB | Math |
-----------------------------------
Reason2
10 Jan 2015 (Evening)
| No | studentid | Fullname | Program | Coursename |
-------------------------------------------------------
| 3 | 3333333 | Hawk | ProgB | Math |
-----------------------------------
I want the result to show like :
Reason1
10 Jan 2015 (Morning)
| No | studentid | Fullname | Program | Coursename |
-------------------------------------------------------
| 1 | 111111 | John | ProgA | Math |
---------------------------------------------------------
| 2 | 2222222 | Jane | ProgB | Math |
-----------------------------------
Reason2
10 Jan 2015 (Evening)
| No | studentid | Fullname | Program | Coursename |
-------------------------------------------------------
| 1 | 3333333 | Hawk | ProgB | Math |
---------------------------------------------------------
I want to group table by
Reasonname
Examdate
Examtime
Please help, I'm a newbie.
I've create database in SQLFiddle Here this please try and help:
SQLFiddle
considered that you have a sql result that looks like this, ordered by reason, date and time :
reason.reasonName | examDate | examTime | prefix | studentName | studentSurname | studentCode | ProgramName | courseName
with a few records, like :
1 | someDate1 | someTime1 | A | James | Jim | 123 | PA | PACourse
1 | someDate1 | someTime1 | A | Tommy | Tim | 222 | PC | PCCourse
1 | someDate2 | someTime2 | B | James | Jim | 123 | PB | PBCourse
2 | someDate1 | someTime1 | C | Jamie | Jam | 444 | PD | PDCourse
2 | someDate1 | someTime1 | E | Willy | Wil | 555 | PE | PECourse
2 | someDate2 | someTime2 | F | Cathy | Cat | 777 | PF | PFCourse
2 | someDate2 | someTime2 | G | David | Dav | 844 | PL | PLCourse
2 | someDate3 | someTime3 | L | James | Jim | 123 | PM | PMCourse
3 | someDate4 | someTime4 | W | Ibear | Ibe | 999 | PX | PXCourse
Here, you get this kind of data, you have,
for reason 1 :
2 students with exam at the same day/time (time1)
1 student with axam at another time (time2)
for reason 2 :
2 students with exam at the same day/time (time1)
2 students with exam at the same day/time (time2)
1 student with exam at another time (time3)
for reason 3 :
1 student with exam at time 4
SO, you want to display :
2 tables for reason 1 (time1 / time2)
3 tables for reason 2 (time1 / time2 / time3)
1 table for reason 3
CONSIDERED that the table, when you get it from your SQL is REALLY oredered like what I wrote above, you have to make your checks on fetch :
<?php
//YOU WILL HAVE TO CHECK THESE VARS TO MAKE IT CLEAR, IF SAME TABLE OR NOT
$i = false;
//I use $i as a table detector, false at start, once a table has been opened it is turned as true
$reason = "";
//I will keep the latest reasonName in this
$examDate = "";
//I will keep the latest examDate in this
$examTime = "";
//I will keep the latest examTime in this
$yourDisplay = "";
//In yourDisplay, i keep the text i have to display (tables, data...)
$closeTable = "</tbody></table>";
//This is the code you need to close a table.
while($rowfet = mysql_fetch_array($myselect)){
if(($rowfet['ReasonName']!=$reason)||(DateThai($rowfet['EXAMDATE'])!=$examDate)||(MorningEvening($rowfet['EXAMTIME'])!=$examTime)){
//YOU GET HERE IF YOU HAVE DIFFERENT REASON/DATE/TIME, SO YOU HAVE TO MAKE A NEW TABLE
$reason = $rowfet['ReasonName'];
$examDate = DateThai($rowfet['EXAMDATE']);
$examTime = MorningEvening($rowfet['EXAMTIME']);
//NOW CHECK IF YOU ALREADY HAVE WRITTEN A TABLE BEFORE
if($i == true){
//You already have written a table before
$yourDisplay.=$closeTable;
}else{
//This is the first table you write
$i=true;
}
$yourDisplay.=" <h2>".$reason."</h2>
<h3>".DateThai($examDate)." ".MorningEvening($examTime)."</h3>
<table width='100%' border='1'>
<thead>
<tr>
<th>No.</th>
<th>studentid</th>
<th>fullname</th>
<th>Program</th>
<th>Coursename</th>
</tr>
</thead>
<tbody>
<tr>
<td>".$rowfet['STUDENTCODE']."</td>
<td>".$rowfet['PREFIXABB']." ".$rowfet['STUDENTNAME']." ".$rowfet['STUDENTSURNAME']."</td>
<td>".$rowfet['PROGRAMNAME']."</td>
<td>".$rowfet['COURSENAMEENG']."</td>
</tr>";
}else{
//YOU ARE ALREADY IN A TABLE! WITH SAME REASON/TIME/DATE
//YOUR RECORD JUST NEEDS TO BE ADDED IN A NEW LINE
$yourDisplay.="<tr>
<td>".$rowfet['STUDENTCODE']."</td>
<td>".$rowfet['PREFIXABB']." ".$rowfet['STUDENTNAME']." ".$rowfet['STUDENTSURNAME']."</td>
<td>".$rowfet['PROGRAMNAME']."</td>
<td>".$rowfet['COURSENAMEENG']."</td>
</tr>";
}
}
//ONCE OUT, CLOSE THE LAST TABLE AND DISPLAY YOUR DATA
if($i==1){
$yourDisplay.=$closeTable;
}
echo $yourDisplay;
?>
In My Opinion, this kind of approach should solve your problem IF THE SQL QUERY returns the rows as explained above. (seems like it is the case)
EDIT :
You asked to "not display" the reasonname if it was the same, so just look at the line you see this :
$yourDisplay.=" <h2>".$reason."</h2>
<h3>".DateThai($examDate)." ................ code continue
and replace it with this :
if($rowfet['ReasonName']!=$reason){
$yourDisplay.="<h2>".$reason."</h2>";
}
$yourDisplay.="<h3>".DateThai($examDate)." ".MorningEvening($examTime)."</h3>
<table width='100%' border='1'>
//.... continue the code
You're looping through all your rows and creating a table for each of the rows.
What you want to do is to create a new table only if a sequence of a new ReasonName starts.
$myselect = mysql_query("SELECT reason.ReasonName,tblexam.EXAMDATE,tblexam.EXAMTIME,prefix.PREFIXABB,studentmaster.STUDENTNAME,studentmaster.STUDENTSURNAME,studentmaster.STUDENTCODE,program.PROGRAMNAME,course.COURSENAMEENG FROM reason, formlate, tblexam, studentmaster,prefix, program, course WHERE reason.ReasonID = formlate.ReasonID AND formlate.CLASSID = tblexam.CLASSID AND formlate.COURSEID = formlate.COURSEID AND formlate.ROOMID = formlate.ROOMID AND prefix.PREFIXID = studentmaster.PREFIXID AND formlate.STUDENTID = studentmaster.STUDENTID AND program.PROGRAMID = studentmaster.PROGRAMID AND course.COURSEID = tblexam.COURSEID GROUP BY reason.ReasonID,studentmaster.STUDENTID ORDER BY reason.ReasonID ASC");
<body>
<?php $i =1;
while($rowfet = mysql_fetch_array($myselect)){
?>
<h2><?php echo $rowfet['ReasonName']; ?></h2>
<h3><?php echo DateThai($rowfet['EXAMDATE']) . ' ' . MorningEvening($rowfet['EXAMTIME']); ?></h3>
<table width="100%" border="1">
<thead>
<tr>
<th>No.</th>
<th>studentid </th>
<th>Fullname </th>
<th>Program </th>
<th>Coursename </th>
</tr>
</thead>
<tbody>
<?php echo "You should create a loop here to loop through your ReasonNames"; ?>
<tr>
<td align="center"><?php echo $i; ?></td>
<td><?php echo $rowfet['STUDENTCODE']; ?></td>
<td><?php echo $rowfet['PREFIXABB'] . $rowfet['STUDENTNAME'] . ' '.$rowfet['STUDENTSURNAME']; ?></td>
<td><?php echo $rowfet['PROGRAMNAME']; ?></td>
<td><?php echo $rowfet['COURSENAMEENG']; ?></td>
</tr>
<?php echo "Your loop should end here"; ?>
</tbody>
</table>
<?php $i++; } ?>

PHP: Fill fixed size chart with mysql data

I have a table chart. Lets say 5 by 5. I run a loop such as
<table>
<tbody>
<?php for ($i = 0; $i < 5; $i += 5) {
echo "<tr>
<td>one box</td>
<td>one two</td>
<td>one three</td>
<td>one four</td>
<tr>";
}?>
</tbody>
</table>
It creates a table such as
| | | | | |
-------------------------------------
| | | | | |
-------------------------------------
| | | | | |
-------------------------------------
| | | | | |
-------------------------------------
| | | | | |
-------------------------------------
Now I have mysql data I load for my purposes and I need it to put the data in respectively so the table looks like
| | | | | |
-------------------------------------
| | | | | |
-------------------------------------
| | Res 1| | | |
-------------------------------------
| | | | Res 3| |
-------------------------------------
| |Res 4 | | | Res 2|
-------------------------------------
How would I do this? I have 50 results and need to fill the results into the correct column and row. I need to do some sort of if(results[0-50]['id'] == rowcolumnid) echo the results for the correct table while doing the for loop.
Edit: Here is my full code.
<table id="schedule">
<tbody>
<?php
$time = mktime(0, 0, 0, 1, 1);
for ($i = 28800; $i < 62200; $i += 1800) { ?>
<tr id="row<?php echo $i; ?>">
<td id="hour">
<?php
printf('%1$s',date('g:i a', $time + $i));
?>
</td>
<td id="sunday"></td>
<td id="monday"></td>
<td id="tuesday"></td>
<td id="thursday"></td>
<td id="friday"></td>
<td id="saturday"></td>
</tr>
<?php } ?>
</tbody>
</table>
My mysql results are in datetime format that I'm going to use to propogate the table.
Results:
ID| EVENT NAME | DATEOFEVENT
1 | event name | 2012-11-20 12:00:00
2 | event name | 2012-11-21 13:30:00
3 | event name | 2012-11-22 13:00:00
4 | event name | 2012-11-23 11:00:00
5 | event name | 2012-11-24 08:00:00
etc.
I can do a strtotime of the dates and a date command to match.
If you first fetch the data (or if it is sorted if you first fetch the first data), then you can just iterate over the data when you match the hour/time that you iterate over to draw the table.
As an example, I've chosen to display only one column that represents 5 hours (1-5) of which some can be matched. Those that are matched, are stored in an array and made available as an iterator (ArrayIterator):
$data = [3,5];
$datas = new ArrayIterator($data);
$datas->rewind();
Matched hours are represented with 1, unmatched ones with 0:
echo "+---+---+\n";
foreach(range(1, 5) as $hour)
{
if ($hasData = ($datas->valid() and $datas->current() === $hour)) {
$datas->next();
}
$hasData = (int) $hasData;
echo "| $hour | $hasData |\n";
echo "+---+---+\n";
};
Output:
+---+---+
| 1 | 0 |
+---+---+
| 2 | 0 |
+---+---+
| 3 | 1 |
+---+---+
| 4 | 0 |
+---+---+
| 5 | 1 |
+---+---+
This works perfectly if the data from the data is available as an iterator (often the case, for mysql_* you need to write you one) and if it is sorted.
Even this is only a single list here, for a table this works actually equally because a table is just a different form of representing the data.

How to echo specific data in loop with a condition specific to the last row

For an accounting system, I'm using PHP & MySQL. I've two tables "GROUP" and "ACHEADS".
In the GROUP table, I have:
---------------------
| id (AI) | group |
---------------------
| 1 | Group 1 |
| 2 | Group 2 |
---------------------
In the ACHEADS table, I have:
-----------------------------------------
| id (AI) | ac_head | amount | j_id |
-----------------------------------------
| 1 | Something 1 | 2000 | 1 |
| 2 | Something 2 | 1000 | 1 |
| 3 | Something 3 | 5000 | 2 |
| 4 | Something 4 | 4000 | 2 |
| 5 | Something 5 | 8000 | 2 |
-----------------------------------------
I've joined the two tables as GROUP.id <<->> ACHEADS.j_id
Now I need to preview the data like this:
----------------------------------------------
Particulars | Details | Total |
----------------------------------------------
Group 1 | | |
Something 1 | 2000 | |
Something 2 | 1000 | 3000 |
----------------------------------------------
Group 2 | | |
Something 3 | 5000 | |
Something 4 | 4000 | |
Something 5 | 8000 | 17000 |
----------------------------------------------
GRAND TOTAL | | 20000 |
------------------------------------==========
Challenges
The table will be dynamic and will generate within a PHP loop (I'm
using a WHILE loop)
Remember: it's a table and if I miss echoing a td, then the table will break up
Problems
When I'm using the loop it's echoing the data on the Details td
accurately. But the sum of the details row according to j_id is also
echoing in each td
Preview here:
----------------------------------------------
Particulars | Details | Total |
----------------------------------------------
Group 1 | | |
Something 1 | 2000 | 3000 |
Something 2 | 1000 | 3000 |
----------------------------------------------
Group 2 | | |
Something 3 | 5000 | 17000 |
Something 4 | 4000 | 17000 |
Something 5 | 8000 | 17000 |
----------------------------------------------
My thoughts
If I can check whether it is the last data of the query, if isset,
then echo the total amount with it's td. (But remember the
Challenge#2)
Does it require a foreach loop?
I failed
I tried checking max(id), it works fine in SQL, but can't use it in
condition within a loop.
(If you still can't understand me, then on the second phase, I'll post my code.)
I would do 2 loops:
Fetch id from GROUP
Fetch amount from ACHEADS based on j_id
This would look something like (non-tested code):
echo '<table><tr><td>Particulars</td><td>Details</td><td>Total</td></tr>';
$total = 0;
$q1 = "SELECT id FROM `GROUP`";
$res1 = mysqli_query($q1);
while($row1 = mysqli_fetch_assoc($res1)) {
echo
$group_total = 0;
$j_id = $row1[id];
$q2 = "SELECT ac_head, amount FROM ACHEADS WHERE j_id = $j_id";
$res2 = mysqli_query($q2);
while($row2 = mysqli_fetch_assoc($res1)) {
echo '<tr><td>' . $row2[ac_head] . '</td>';
echo '<td>' . $row2[amount] . '</td></tr>';
$group_total = $group_total + $row2[amount];
$total = $total + $row[amount];
}
echo '<tr><td colspan="3" align="right">' . $group_total . '</td></tr>';
}
echo '<tr><td>GRAND TOTAL</td>';
echo '<td colspan="2" align="right">' . $total . '</td></tr>';
echo "</table>";
njk rockz!
It worked nicely. Thanks a lot, brother - it helped me a lot, I can't explain.
Here is my final code:
<tr style="background: #000; color:#fff;">
<th style="width:150px;">Particulars</th>
<th>Details</th>
<th>Amount</th>
</tr>
<tr>
<td>Opening Balance</td>
<td></td>
<td>500000</td> <!-- till not dynamic -->
</tr>
<?php
$total = 0;
$se = "SELECT * FROM group";
$res = mysql_query($se) or die (mysql_error());
while ($row = mysql_fetch_array($res))
{
?>
<tr>
<td colspan="3" style="font-weight:bold;"><?php echo $row['group']; ?></td>
</tr>
<tr>
<?php
$group_total = 0;
$se1 = "SELECT ac_head, amount FROM `acheads` WHERE `j_Id` = '".$row['id']."'";
$res1 = mysql_query($se1) or die (mysql_error());
while ($row1 = mysql_fetch_array($res1))
{
$group_total = $group_total + $row1['amount'];
?>
<td><?php echo $row1['ac_head']; ?></td>
<td><?php echo $row1['amount']; ?></td>
<td> </td>
</tr>
<?php
}
echo '<tr><td colspan="3" align="right">' . $group_total . '</td></tr>';
}
?>
</table>
</code>

Categories