Using while() display even with NULLS - php

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.

Related

php table <th> and <td> from Database Selected but they are not Matching in the right indexing position

all Developers.
I am developing School Management System, in the Database, I have two tables one is For Subjects, and the other one is designed for obtained marks of the Subjects and it is called scores.
So I am trying to fetch subject Names as Table Head
I have another Query below this query and I am trying to fetch from scores as table data .
At this point, I failed to match the subject name and its score from the scores table.
Here is my code:
<table class="table table-striped table-bordered">
<head>
<tr>
<?php
// Query for Subject Names
$view_subject = $config->prepare("SELECT * FROM subjects");
$view_subject->execute();
while($row = $view_subject->fetch()){
$sub_name = htmlspecialchars($row['sub_name']);
?>
<th class="text-center"style="background-color:#395C7F;color:#fff;"><?php echo $sub_name;?></th>
<?php } ?>
</tr>
</thead>
<body>
<?php
// Query for Subject Scores
$view_scores = $config->prepare("SELECT * FROM scores INNER JOIN subjects ON scores.score_sub_id = subjects.sub_id WHERE scores.std_rand = :random_id ORDER BY scores.score_sub_id ASC");
$view_scores->execute(['random_id' => $rand_ID]);
while($row = $view_scores->fetch()){
$score_id = htmlspecialchars($row['score_id']);
$score_sub_id = htmlspecialchars($row['score_sub_id']);
$score_mid_amount = htmlspecialchars($row['score_mid_amount']);
$score_final_amount = htmlspecialchars($row['score_final_amount']);
?>
<tr>
<td class="text-black" data-title="Subject"><?php echo $score_mid_amount;?></td>
</tr>
<?php } ?>
</tbody>
</table>
Database images:
1- Subjects table
2- Scores table
** Browser UI **
On your second loop you have entered '<tr>' wrapping each '<td>' that means that each one arrives at a different line , '<td>'s should be as much as there are '<th>' for each line.... so :
<?php
// Query for Subject Scores
$view_scores = $config->prepare("SELECT * FROM scores INNER JOIN subjects ON scores.score_sub_id = subjects.sub_id WHERE scores.std_rand = :random_id ORDER BY scores.score_sub_id ASC");
$view_scores->execute(['random_id' => $rand_ID]);
?>
<tr>
<?php
while($row = $view_scores->fetch()){
$score_id = htmlspecialchars($row['score_id']);
$score_sub_id = htmlspecialchars($row['score_sub_id']);
$score_mid_amount = htmlspecialchars($row['score_mid_amount']);
$score_final_amount = htmlspecialchars($row['score_final_amount']);
?>
<td class="text-black" data-title="Subject"><?php echo $score_mid_amount;?></td>
<?php } ?>
</tr>
</tbody>
</table>
This should fix your table but it will only create one line! if you have more than one line you will need to add another loop to wrap this one and it will create the new '<tr>' outside the inner loop.
BTW: I assume that the 2nd while loop is exactly long as the first one... since you are supposed to have the same amount of <td> per line per <th> if it's not in the same length or not sorted the same way you will have an issue... which can be resolved either by adjusting your SELECT or creating an array with ids and injecting to it the data from the second loop according to the keys brought in the first.

How do I add another mysqli query into a while loop?

So I am carrying out a query and returning the results in the form of a table. The code below works well.
<table>
<thead>
<tr style="text-align: center;">
<th>Activity</th>
<th>Description</th>
<th>Frequency</th>
<th>Mandatory</th>
<th>Added Yet</th>
</tr>
</thead>
<tbody>
<?php
$stmt = $conn->prepare("SELECT * FROM knowledgebase ORDER BY category ASC");
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) echo "<tr><td>No activities found</td><td></td><td></td><td></td><td></td><td></td></tr> </tbody>
</table></br></br>
Why not add your first activity from our Knowledge base or create a new activity of your own";
else {
while($row = mysqli_fetch_array($result)) {
$activity_id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$frequency = $row['frequency'];
$mandatory = $row['mandatory'];
echo "<tr><td>".$title."</td><td>".$description."</td><td style=\"text-align: center;\">".$frequency."</td><td style=\"text-align: center;\">".$mandatory."</td><td></td></tr>";
}
}
$stmt->close();
?>
</tbody>
</table>
What I want to add in is another query inside the final <td></td>. What I want to do is query a second db table and say if this activity has already been added to the users table, echo YES, otherwise, echo NO.
The problems is, adding the query into the while loop keeps throwing errors.
Any suggestions gratefully received.
Instead of running another query for every row, you could join the users table to the knowledgebase table in your first query. If you use a left join, you'll still get all the rows from knowledgebase.
SELECT knowledgebase.*, userstable.activity_id
FROM knowledgebase
LEFT JOIN userstable ON knowledgebase.id = userstable.activity_id
ORDER BY category ASC
Then in your last <td>, you can print YES/NO depending on whether or not there was a matching row in the users table.
...<td><?php echo $row['activity_id'] ? 'YES' : 'NO' ?></td>...
(I made up names for your other table and column, but I think it shows the general idea.)

display the data which contains multiple result

This is again an extended quetion of THIS.
I changed my table format, i mean i have created a separate table for vendor_locations where i store multiple locations against that vendor id in multiple rows. and also created a table vendor_products to store multiple products for that vendor.
Now my problem is, As both products and locations will be multiple for each vendor while displaying i am not getting how to display it in a single row.
if the products are 3 and location is 2 then, all the details will be displayed thrice. if i remove either location or product it will work properly. But how can i do this for both
if(isset($_POST['submit']))
{
$sql="SELECT vendor.id AS venid
, vendor.name AS VNAME
, vendor.category
, vendor.website
, vendor.email
, vendor.phone
, vendor.vat
, vendor.pan
, items.name AS iname
, location.name AS locname
, items.item_id
FROM vendor
INNER JOIN vendor_location ON vendor.id = vendor_location.vendor_id
INNER JOIN vendor_products ON vendor.id=vendor_products.vendor_id
INNER JOIN location ON vendor_location.location = location.loc_id
INNER JOIN items ON vendor_products.item_id=items.item_id
ORDER BY vendor.id";
}
$sql1 = mysql_query($sql) or die(mysql_error());
}
?>
<div class="w-box w-box-blue">
<div class="w-box-header">
<h4>Vendor</h4>
</div>
<div class="w-box-content">
<table id="dt_hScroll" class="table table-striped">
<thead><tr>
<th>Vendor ID</th>
<th>Vendor</th>
<th>Category</th>
<th>Website</th>
<th>Email</th>
<th>Phone</th>
<th>VAT</th>
<th>PAN</th>
<th>Products</th>
<th>Locations</th>
</tr>
</thead>
<tbody>
<?php
$current = ''; // STORE THE SUPPLIER SID
while($row = mysql_fetch_array($sql1)) {
if ($row['venid'] != $current) {
echo "<tr>
<td><a href='edit_vendor_details.php?id=$row[venid]'>{$row['venid']}</a></td>
<td>{$row['VNAME']}</td>
<td>{$row['category']}</td>
<td>{$row['website']}</td>
<td>{$row['email']}</td>
<td>{$row['phone']}</td>
<td>{$row['vat']}</td>
<td>{$row['pan']}</td>
";
$current = $row['venid']; // RESET STORED SID
}
else {
echo "<tr><td colspan='8'> </td>";
}
echo "<td>{$row['iname']}</td>";
echo "<td>{$row['locname']}</td>";
echo "</tr>";
}
echo('</tbody></table>');
?>
</tbody></table>
use group_concat on the fields if you only wish to show. like this:
SELECT vendor.id AS venid --rest of selection
, GROUP_CONCAT(location.name) AS locname
, GROUP_CONCAT(items.item_id)
FROM vendor --rest of your joins
GROUP BY vendor.id
see more about it here: MySQL Aggregate Functions

How to display combined rows in the database table with same ID

i have a question for the experts. I have no idea how to combine all the order ID with the same ID,
like in the picture, all orders with order ID = 1 are in one transaction, how do i combine all order IDs with the same id and display only one total price for all of the proudcts bought. and since all order ID are the same so the deliver and payment option will also be the same just need to display one row.
and a follow up question is how will i also show all the products bought if i combine all the same order IDs, compute the total price and display delivery and payment option in one single row
Here is the picture for my database relationship, i just followed the ones on the internet. the only difference is that "products" are changed to "inventory" and "serial" in products are changed to "prod_id"
here are my codes to display the current picture.
<?php
session_start();
$conn = #mysql_connect("localhost","root","");
$db = #mysql_select_db("");
$qry = "SELECT customers.name,customers.payment,customers.carrier, orders.date, order_detail.productid, order_detail.quantity, order_detail.price, order_detail.orderid, inventory.prod_name
FROM customers
RIGHT JOIN orders on customers.serial=orders.serial
RIGHT JOIN order_detail on orders.serial=order_detail.orderid
LEFT JOIN inventory on order_detail.productid=inventory.prod_id where customers.email='{$_SESSION['email']}'";
mysql_set_charset("UTF8");
$result = #mysql_query($qry);
if($result === FALSE) {
die(mysql_error()); // TODO: better error handling
}
echo "<center>";
echo "<table class='CSSTableGenerator'>
<tr>
<td>Date of Purchase</td>
<td>First Name</td>
<td>Order ID</td>
<td>Products</td>
<td>Quantity</td>
<td>Total Price</td>
<td>Delivery Option</td>
<td>Payment Option</td>
<tr>";
while ($row=mysql_fetch_array($result)){
echo "<tr>";
echo "<td>".$row['date']."</td>";
echo "<td>".$row['name']."</td>";
echo "<td>".$row['orderid']."</td>";
echo "<td>".$row['prod_name']."</td>";
echo "<td>".$row['quantity']."</td>";
echo "<td>".($row['price']*$row['quantity'])."</td>";
echo "<td>".$row['carrier']."</td>";
echo "<td>".$row['payment']."</td>";
echo "</tr>";
}
echo "</table>";
?>
</table>
It seems that what you're needing to learn for this particular question is the SQL Group By clause.
This (untested, might need minor tweaking) should do the trick. Note that you don't get order item quantities out of this, but I would say that it's possible to get them.
SELECT o.date, c.name, o.serial as 'Order Id', GROUP_CONCAT(p.name) as 'Products', SUM(od.price) as 'Total', c.carrier, c.payment
FROM orders o
JOIN customers c on o.customer_id = c.serial
JOIN orderdetail od on o.serial = od.orderid
JOIN products p on od.productid = products.prod_id
GROUP BY o.serial
Of particular note is a handy aggregate function in MySQL called GROUP_CONCAT.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

AVG function in SELECT affects the number of rows in query output

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>".

Categories