I am trying to create a table that displays member data for three different types of members - it should display how many members were added each day, and then there needs to be a column that keeps a cumulative total month to date for the three different types of members. Example:
Members Added in March:
Date Type A Type A Total Type B Type B Total
1 23 23 16 16
2 13 36 13 29
3 16 52 17 46
My query looks like this:
$results=$wpdb->get_results("SELECT DAY(Subscription_Start_Date) as dayOfMonth, COUNT(a.user_id) as typeA, COUNT(b.user_id) as typeB, COUNT(c.user_id) as typeC
FROM users u
LEFT OUTER JOIN typeAUser a ON u.type_id = a.User_Id
LEFT OUTER JOIN typeBUser b ON u.type_id = b.User_Id
LEFT OUTER JOIN typeCUser c ON u.type_id = c.user_Id AND c.phone_opt_out != '1'
WHERE MONTH(Subscription_Start_Date) = MONTH(curdate()) AND YEAR(Subscription_Start_Date) = YEAR(curdate())
GROUP BY DAY(Subscription_Start_Date)
ORDER BY DAY(Subscription_Start_Date)");
I am outputting the data into a table using a foreach loop like so:
$resultTable = "<table><thead>
<tr><td colspan='7'>Month to Date Members Added $currentMonth</td></tr>
<tr>
<th>Day of the Month</th>
<th>Type A</th>
<th>Type A Month to Date</th>
<th>Type B</th>
<th>Type B Month to Date</th>
<th>Type C</th>
<th>Type C Month to Date</th>
</tr></thead><tbody>";
foreach($results as $r){
$aMemPerDay = $r->typeA;
$bMemPerDay = $r->typeB;
$cMemPerDay = $r->typeC;
$resultTable .= "<tr>
<td>$r->dayOfMonth</td>
<td>$aMemPerDay</td>
<td>???</td>
<td>$bMemPerDay</td>
<td>???</td>
<td>$cMemPerDay</td>
<td>???</td>
</tr>";
}
$resultTable .="</tbody></table>";
echo $resultTable;
The query returns the info I need for the number of members added per day, but I can't figure out how to keep a running total that increase each day. I have tried many things, but nothing seems to work. I tried implementing a variation of this solution within the foreach on each of the member types but when I put the $totalA variable into the table, it just printed out Array:
$totalA = array();
$runningSumA = 0;
foreach ($aMemPerDay as $aMem) {
$runningSumA += $aMem;
$totalA[] = $runningSum;
}
I even tried using a MySQL variable in the query (since there are only 30 days per month, I figured it wouldn't be overly cumbersome), but I wasn't able to get a cumulative result there either. I know that there is probably some manageable answer out there, but I can't seem to come up with it. Any direction would be appreciated!
$TotalA = 0;
$TotalB = 0;
$TotalC = 0;
foreach($results as $r){
$aMemPerDay = $r->typeA;
$bMemPerDay = $r->typeB;
$cMemPerDay = $r->typeC;
$TotalA += $aMemPerDay;
$TotalB += $bMemPerDay;
$TotalC += $bMemPerDay;
$resultTable .= "<tr>
<td>$r->dayOfMonth</td>
<td>$aMemPerDay</td>
<td>???</td>
<td>$bMemPerDay</td>
<td>???</td>
<td>$cMemPerDay</td>
<td>???</td>
</tr>";
}
Related
I'm struggeling to get the corresponding values from table b using while loops. I have the following data in my database:
Table A
number - entity
3000 - ent1
3010 - ent1
4000 - ent1
Table B
number - entity
3000 - 10
3010 - 10
3010 - 20
4000 - 20
3000 - 30
4000 - 30
Now, I need the data to output the following table, where the first column is from table a and the next columns are populated from table b:
ent1 - 10 - 20 - 30
3000 - 3000 - null - 3000
3010 - 3010 - 3010 - null
4000 - null - 4000 - 4000
I have tried combining two WHILE loops, but with no success:
$query_entity = "SELECT number, entity FROM table_a ORDER BY number ASC";
$result_entity = mysqli_query($mysqli, $query_entity);
while ($entities = mysqli_fetch_array($result_entity)) {
$entitiesAccount = $entities['number'];
$query_entity_tabtwo = "SELECT number, entity
FROM table_b
WHERE number = $entitiesAccount";
$result_entity_tabtwo = mysqli_query($mysqli, $query_entity_tabtwo);
while ($entities_tabtwo = mysqli_fetch_array($result_entity_tabtwo)) {
echo $entitiesAccount . " - " . $entities_tabtwo['number'];
}
}
The result I'm getting is not the one I want stated above because the result does not separate the "entity" field in table b. How can I alter my script to get the desired result?
You simply need to echo things in a slighly different place
$sql = "SELECT number, entity
FROM table_a
ORDER BY number ASC";
$result = mysqli_query($mysqli, $sql);
while ($row = mysqli_fetch_array($result_entity)) {
$entitiesAccount = $row['number'];
$sql = "SELECT number, entity
FROM table_b
WHERE number = $entitiesAccount";
$result2 = mysqli_query($mysqli, $sql);
echo $entitiesAccount;
while ($row2 = mysqli_fetch_array($result2)) {
echo " - " . $row2['number'];
}
echo '<br>';
}
Cue: This is where JOINS join us in this endeavor. BA DUM TSSSS
You can use the ANSI syntax or the traditional where clause, they both work the same.
In your case, you could write something like..
SELECT ta.number, tb.entity
FROM tableA as ta
LEFT JOIN tableB as tb ON tb.number = ta.number
WHERE ta.entity = 'ent1'; // I suppose this is where you do the selection
Now you have all the rows from tableA and respectively related rows from tableB
and lets say that you have fetched all the result inside the array variable named.... umm.... $result.
Now, All you need is a little metaphorical sleight of hand in php as below...
<?php
$result = []; // This comes from the mysql
$output = [];
$columns_raw = [];
$entity_name = 'ent1'; // This comes from your selection logic the same that goes to sql.
foreach ($result as $row) {
$columns_raw[] = $row['entity'];
$output[$row['number']][$row['entity']][] = $row;
}
$columns = array_unique($columns_raw);
?>
let me write you a little html too.
<table>
<thead>
<th><?php echo $entity_name; ?></th>
<?php foreach ($columns as $column) { ?>
<th><?php echo $column; ?></th>
<?php } ?>
</thead>
<tbody>
<?php foreach ($output as $number => $row) { ?>
<tr><?php echo $number; ?></tr>
<tr><?php
foreach ($columns as $column) {
if (array_key_exists($column, $row)) {
echo $number;
} else {
echo 'null';
}
}
?></tr>
<?php } ?>
</tbody>
</table>
...and voila!
NOTE:- This is totally something which can be called a 'blind code' and I didn't run it. But this should be enough to point you in the right direction.
You can generate the data entirely in one query. This way you can simplify your PHP to one while loop:
SELECT a.number AS ent1,
GROUP_CONCAT(CASE WHEN b.entity = 10 THEN b.number END) AS `10`,
GROUP_CONCAT(CASE WHEN b.entity = 20 THEN b.number END) AS `20`,
GROUP_CONCAT(CASE WHEN b.entity = 30 THEN b.number END) AS `30`
FROM table_a a
JOIN table_b b ON b.number = a.number
GROUP BY ent1
Output:
ent1 10 20 30
3000 3000 (null) 3000
3010 3010 3010 (null)
4000 (null) 4000 4000
Demo
How to display all date of the month and total earning of each day. I think my monthlyreport.php wrong badly. I no idea how to do it. Please help me to solve the problem. This is important for me. Thank you for your help.
My output something like this:
Month November
No Date Total earning
1 1/11/2014 100
2 2/11/2014 200
3 3/11/2014 400
My database something like this:
//tblvisit
Id VisitDate PatientId PatientName DoctorName Symptom Test Diagnosis TotalPrice
1 2014-11-05 123 John mr wong flu checking panadol 31
My monthlyreport.php:
<tr>
<td>No</td>
<td>Date</td>
<td>Total Earned</td>
</tr>
<?php
for($i=0;$i<mysql_num_rows($SearchResult); $i++)
{
$visitRec = mysql_fetch_array($SearchResult);
echo "<tr> ";
echo "<td>".($i+1)."</td>";
echo "<td>".$visitRec['VisitDate']."</td>";
$total = 0;
$id = $visitRec['Id'];
$date = $_POST['txtSMonth'];
$data = mysql_query("SELECT * FROM tblvisit WHERE VisitDate ='$date'") or die(mysql_error());
while($row= mysql_fetch_array( $data ))
{
$total += $row['TotalPrice'];
}
echo "<td>".$total."</td>";
echo "</tr>";
}?>
Use the following query as inner query :
SELECT sum(TotalPrice) FROM tblvisit WHERE VisitDate ='$date' group by VisitDate
Hope it will work for you.
Below is my Query:
$query = "
SELECT *
FROM Teacher t
INNER JOIN Session s ON t.TeacherId = s.TeacherId
JOIN Grade_Report gr ON s.SessionId = gr.SessionId
WHERE
('".mysql_real_escape_string($sessionid)."' = '' OR gr.SessionId = '".mysql_real_escape_string($sessionid)."') ";
The results are stored in a table which code looks like this:
<table border='1'>
<tr>
<th>Session ID</th>
<th>Student Username</th>
<th>Student Name</th>
<th>Mark</th>
<th>Grade</th>
</tr>
<?php
while ($row = mysql_fetch_array($result)) {
echo "
<tr>
<td>{$row['SessionId']}</td>
<td>{$row['StudentUsername']}</td>
<td>{$row['StudentForename']} {$row['StudentSurname']}</td>
<td>{$row['Mark']}</td>
<td>{$row['Grade']}</td>
</tr>";
}
This query outputs 13 rows in the results which is fine when it selects all rows.
Now what happens is that I want the average mark for each session. So I include 'AVG(gr.Mark) as AvgMark' in the query and include <td>{$row['AvgMark']}</td> in the table. The Calculation it outputs is correct The problem is that the query now only outputs 1 row which is the top row of the query result. I understand this as AVG(gr.Mark) only requires one row when outputted.
So my question is that except using SELECT'AVG(gr.Mark) as AvgMark' in the query to find average marks of each session, is there a way I can workout average of each mark outside the query by using php so that the query output shows the 13 rows and is not affected and I can store the calculation of the average below the table rather than in the table?
The reason AVG returns one row is that it's an aggregate function, and without a GROUP BY clause operates on all rows.
Averages in PHP are just like averages everywhere else; total your values and divide by the number of samples. Hence, you can easily calculate the average in code by changing the code to:
<?php
$total = 0;
$count = 0;
while ($row = mysql_fetch_array($result)) {
$count++;
$total += $row['Mark'];
echo "
<tr>
<td>{$row['SessionId']}</td>
<td>{$row['StudentUsername']}</td>
<td>{$row['StudentForename']} {$row['StudentSurname']}</td>
<td>{$row['Mark']}</td>
<td>{$row['Grade']}</td>
</tr>";
}
$average = (int)($total/$count);
echo "<tr><td colspan=3></td><td>Average</td><td>$average</td></tr>".
I have put together the following code, the problem is that each while loop is only returning one set of data.
$result = mysql_query("SELECT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' GROUP BY date");
$i = 1;
echo "<table cellspacing=\"10\" style='border: 1px dotted' width=\"300\" bgcolor=\"#eeeeee\">";
while ($row = mysql_fetch_assoc($result))
{
$date=date("F j Y", $row['date']);
echo $date;
echo "
<tr>
<td>Fixture $i - Deadline on $date</td>
</tr>
";
$result = mysql_query("SELECT * FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' AND date = '$row[date]' ORDER BY date");
while ($row = mysql_fetch_assoc($result))
{
extract ($row);
echo "
<tr>
<td>$home_user - $home_team V $away_user - $away_team</td>
</tr>
";
}
$i++;
}
echo "</table>";
I should get many dates, and then each set of fixture below.
At the moment, the first row from the first while loop is present, along with the data from the second while loop.
However, it doesn't continue?
Any ideas where I can correct this?
Thanks
Replace
$result = mysql_query("SELECT * FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' AND date = '$row[date]' ORDER BY date");
while ($row = mysql_fetch_assoc($result))
with
$result1 = mysql_query("SELECT * FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' AND date = '$row[date]' ORDER BY date");
while ($row = mysql_fetch_assoc($result1))`
What happens with your current code is that after executing internal while, next call (in external loop)to mysql_fetch_assoc($result) always returns false (because you just iterated through it in internal loop). All you need is to use a different variable in internal loop.
You're overwriting the $result variable. Change the second one to $result2 or something and see what happens. Make sure you do it when you set the variable, and use it in the query.
You are changing your $result variable in your loop so it is at the end after the inner while loop has run.
you just mixing variables. second result and row should be named differently.
though it would be better to make it with one single query
Well you've got the answer to your question.
I just want to add that usually you can write a smarter SQL query and manage without an inner query with it's loop. And your code will work a lot faster if you'll have 1 query instead of N+1.
LEFT JOIN usually can be used to replace inner looping. Example:
SELECT DISTINCT A.date, B.* FROM table_fixtures A
LEFT JOIN table_fixtures B ON A.date = B.date
WHERE B.compname = "a value"
However this time it looks illogical. I think what you actually do is achievable with a simple query like this:
SELECT * FROM table ORDER WHERE compname="something" ORDER BY date
You are reusing the same variables over for your inner loop and its breaking the outer loop.
Change your inner loop to something like:
$result2 = mysql_query("SELECT * FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' AND date = '$row[date]' ORDER BY date");
while ($row2 = mysql_fetch_assoc($result2))
{
extract ($row2);
echo "
<tr>
<td>$home_user - $home_team V $away_user - $away_team</td>
</tr>
";
}
On a different note - why do you have a GROUP BY date in the first row, when all you have in the projection list is the date?
I have a table and I am displaying its contents using PHP and a while(); I have about three fields in the table that are NULL but can be change, but I want them to still display all the results in my table.
But, it only shows the records with data in EVERY field. Anyone how I can display it? I get a count of the table and it gives me 2, but only displays one.
<h3>Viewing All Updates</h3>
<h4>Below are all active updates for COTC</h4>
<table>
<thead>
<tr>
<th>Site Name</th>
<th>Page</th>
<th>Flag</th>
<th>Date Sent</th>
<th>View</th>
</tr>
</thead>
<tbody>
<?php
$sql = "SELECT sname,page_name,date_submitted,u_id,clients.c_id,flag,completed FROM updates INNER JOIN clients ON updates.c_id = clients.c_id INNER JOIN pages ON updates.page = pages.p_id ORDER BY date_submitted DESC";
$query = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($query)){
$completed = $row['completed'];
if($completed == 1){
print '<tr class="quiet">';
}else{
print '<tr>';
}
print '<td>'.$row['sname'].'</td>';
print '<td>'.$row['page_name'].'</td>';
print '<td>'.$row['flag'].'</td>';
print '<td>'.$row['date_submitted'].'</td>';
print '<td class="center"><img src="images/page_edit.png" alt="Edit entry!" /></td>';
print '</tr>';
}
?>
</tbody>
</table>
Your PHP is correctly printing every row returned. I believe your problem is in the query.
SELECT sname,page_name,date_submitted,u_id,clients.c_id,flag,completed
FROM updates INNER JOIN clients ON updates.c_id = clients.c_id
INNER JOIN pages ON updates.page = pages.p_id
ORDER BY date_submitted DESC
This query will only return a row in updates if it has a matching one in clients and a matching one in pages. If you want the clients or the pages joins to be optional (a updates row that has c_id or page of NULL will still return) change them from INNER JOINs to LEFT JOINs.