MySQL show all rows and sum at the end - php

I've read through about 20 different answers regarding this question, but either I'm mis-understanding the answers, or its just not clicking. Here is my situation:
I have a table that lists ingredients for a recipe. Columns in the table are: ingredient_id, ingredient_title, ingredient_oz, ingredient_grams, ingredient_lbs (pounds), etc.
I want to list each ingredient, then after all ingredients have been listed, add a final row that sums up all the oz, grams, lbs, etc. Below is an example of the output I am trying to achieve.
Example:
INGREDIENT TITLE OZ GRAMS LBS
ingredient1 4 6 3
ingredient2 1 2 4
ingredient3 9 4 4
TOTAL 14 12 11
My first thought was simply using SUM() AS in the SQL
SELECT ingredient_title, ingredient_oz, ingredient_lbs, ingredient_grams, SUM(ingredient_oz) as oz_sum, SUM(ingredient_lbs) as lbs_sum, SUM(ingredient_grams) as grams_sum FROM ingredients
And here is the code on my page:
<!-- Beginning of table is here -->
<?php
while ($ingredientRow = $ingredients->fetch_assoc()) { ?>
<tr>
<td><?php echo $ingredientRow["ingredient_title"]; ?></td>
<td><?php echo $ingredientRow["ingredient_oz"]; ?></td>
<td><?php echo $ingredientRow["ingredient_lbs"]; ?></td>
<td><?php echo $ingredientRow["ingredient_grams"]; ?></td>
</tr>
<?php } ?>
</tbody>
<tfoot>
<tr>
<td>TOTALS</td>
<td><?php echo $ingredientRow["oz_sum"]; ?></td>
<td><?php echo $ingredientRow["lbs_sum"]; ?></td>
<td><?php echo $ingredientRow["grams_sum"]; ?></td>
</tr>
</tfoot>
</table>
<?php }?>
However all that does is return the first row (ingredient 1), and doesn't return the remaining rows or the sum. Then as I continued to read about this, I saw a low of people discussing using "group by" as well. So then I tried:
SELECT ingredient_title, ingredient_oz, ingredient_lbs, ingredient_grams, SUM(ingredient_oz) as oz_sum, SUM(ingredient_lbs) as lbs_sum, SUM(ingredient_grams) as grams_sum FROM ingredients GROUP BY ingredient_title
That returns all the rows, but again doesn't return a sum. Am I grouping by the wrong field? Do I need to group each of the fields I'm trying to sum?

When you run a query, you will get the data back that you ask for, so basically if you run a query to return all the rows individually - you will get those back, without the total. If on the other hand you run a query to get only the sum/totals, you won't get the individual rows of data.
There are two ways to get what you want. One is done via a query, one is done via PHP itself.
You can write a union query to get the individual rows of data, then return the sums, something like this:
SELECT
ingredient_title,
ingredient_oz,
ingredient_lbs,
ingredient_grams
FROM
ingredients
union all
SELECT
ingredient_title,
SUM(ingredient_oz) as oz_sum,
SUM(ingredient_lbs) as lbs_sum,
SUM(ingredient_grams) as grams_sum
FROM
ingredients
Which will return both.
Or you can write a quick snippet of PHP code to do the addition for you in your code based on the first part of the query:
<?php
$sql="SELECT
ingredient_title,
ingredient_oz,
ingredient_lbs,
ingredient_grams
FROM
ingredients";
//Execute query:
while($result)
{
echo $result['ingredient_title'];
echo $result['ingredient_oz'];
// etc etc. Format as needed...
$ingOz+=$result['ingredient_oz'];
$ingLbs+=$result['ingredient_lbs'];
$ingGrams+=$result['ingredient_grams'];
}
// And now the totals:
echo $ingOz;
echo $ingLbs;
// etc etc.
?>
I would personally probably use the second approach - you don't need to make the database run the query twice just to get the results - and you are already getting all the individual rows of data, therefore you may as well simply keep a simple running total in a variable to be displayed as needed.

Don't be afraid to run 2 separate SQL queries, because:
Grouping (for sum) works differently
Also code logic will more readable and decoupled
$query = "
SELECT
ingredient_title,
ingredient_oz,
ingredient_lbs,
ingredient_grams
FROM ingredients
";
$ingredients = $db->query($query)->fetch_all();
$query = "
SELECT
SUM(ingredient_oz) as oz_sum,
SUM(ingredient_lbs) as lbs_sum,
SUM(ingredient_grams) as grams_sum
FROM ingredients
";
$ingredientSummary = $db->query($query)->fetch_assoc();
<!-- Beginning of table is here -->
<?php
foreach ($ingredients as $ingredientRow) ?>
<tr>
<td><?php echo $ingredientRow["ingredient_title"]; ?></td>
<td><?php echo $ingredientRow["ingredient_oz"]; ?></td>
<td><?php echo $ingredientRow["ingredient_lbs"]; ?></td>
<td><?php echo $ingredientRow["ingredient_grams"]; ?></td>
</tr>
<?php } ?>
</tbody>
<tfoot>
<tr>
<td>TOTALS</td>
<td><?php echo $ingredientSummary["oz_sum"]; ?></td>
<td><?php echo $ingredientSummary["lbs_sum"]; ?></td>
<td><?php echo $ingredientSummary["grams_sum"]; ?></td>
</tr>
</tfoot>
</table>
<?php }?>

I think you should make it a separate query when selecting the sum. Does it make sense that it can get the sum of each row when the sum is of all the rows? By grouping you cause the SUM to sum each group, and every ingredient is a marked as a group.

its little late, but its easy with a roll back at the end of query
SELECT ingredient_title, ingredient_oz, ingredient_lbs, ingredient_grams
FROM ingredients
WITH ROLL BACK
here some examples from other site
https://www.mysqltutorial.org/mysql-rollup/

Related

Echo multiple values from a single database entry after LEFT JOIN to pull names from a different table

I hope the title makes sense and sorry if this is a duplicate I wasn't certain what to search for to find the correct answer.
I have a table on a website that pulls info from a database. So my issue is I have two tables in the database, the_traveler and the_discipline. What I am doing is pulling the value from the traveler that looks like this 89,43 and after I LEFT JOIN with the_disciplines table, to get the name that correlates with the numbers, like so:
$query ="SELECT t.name,t.traveler_id, t.disciplines, dis.name as discname
FROM ".TABLEPRIFIX."traveler t
LEFT JOIN ".TABLEPRIFIX."discipline dis ON t.disciplines = dis.id";
$disname = $obj->queryResult($query);
I am only able to echo out the first numbers name by doing this:
<?php
foreach($disname as $traveler)
{
<tr>
<td><?php echo $traveler['discname']; ?></td>
</tr>
<?php
}
?>
My question is how would I change my code to get all the numbers from the database to echo in each row. I have tried to implode the numbers.
If you want to get a single row with all values you must change the code to:
<tr>
<?php
foreach($disname as $traveler)
{
<td><?php echo $traveler['discname']; ?></td>
<?php
}
?>
</tr>

Table data is not arranged

as i am a beginner so i want to ask how can i run the multiple queries using PHP for the same row to have multiple data in the table in html. i have tried many attempts but nothing worked i am using MYSQL as backend. I know that i have not written code for the first row and second column i.e. the second <td> on wicket keeper but the thing is that i want all rounder data to come in the second <td> of wicket keeper section. when running this code it is providing the output fine for wicket keeper but for all rounder column the data is starting after the end of wicket keeper data. i know why this problem is occurred but how can i solve this please tell??
CODE HERE:
<?php
$sql="select * from teams where role = 'WicketKeeper'";
$result=mysqli_query($conn,$sql) or die(mysqli_error());
while($row=mysqli_fetch_assoc($result)){
?>
<tr>
<td><?php echo $row["name"] ?></td>
<td></td>
<td></td>
<td></td>
</tr>
<?php } ?>
<?php
$sql="select * from teams where role = 'AllRounder'";
$result=mysqli_query($conn,$sql) or die(mysqli_error());
while($row=mysqli_fetch_assoc($result)){
?>
<tr>
<td></td>
<td><?php echo $row["name"] ?></td>
<td></td>
<td></td>
</tr>
<?php } ?>
Here is a good way to generate the rows of the display you showed.
First, use this query:
SELECT name, role FROM teams ORDER BY role DESC;
It generates rows in the order you want them, wicketkeepers first.
Then, use this php code to generate your display.
<?php
$sql="SELECT name, role FROM teams ORDER BY role DESC";
$result=mysqli_query($conn,$sql) or die(mysqli_error());
while($row=mysqli_fetch_assoc($result)){
$role = $row["role"];
$name = $row["name"];
$wicketkeeper = $role == "WicketKeeper" ? $name : "";
$allrounder = $role == "AllRounder" ? $name : "";
?>
<tr>
<td><?php echo $wicketkeeper ?></td>
<td><?php echo $allrounder ?></td>
<td></td>
<td></td>
</tr>
<?php } ?>
This renders the rows in the result set from your query, placing names in columns according to their roles.
In the general case, this task is known as pivoting a table.
Pro tip 1 Try to avoid SELECT * in queries. Instead give the names of the columns you need. This makes your code easier for a stranger to read, and it may make your queries run faster.
Pro tip 2 Anytime you catch yourself reusing the same query where it only varies by a WHERE clause, try to use a single query. This can make your application run faster.

Use PHP to get SQL data for various IDs

I currently have a table on my website which I have in my SQL database and I need each row of my table to get certain information from the columns. I have something that works just fine at the moment, however, I have a feeling its not the best way of doing things. As I have around 600+ rows in my database.
I'm trying to learn more about all of this so if you have any idea to do this in a better way then that would be fantastic.
<?php
$queryContent="SELECT * FROM businesses WHERE id= 104";
$resultContent= $mysqli->query($queryContent);
$rowContent = $resultContent->fetch_assoc();
?>
<?php if ($rowContent['active'] == "Y") { ?>
<tr>
<td><?php echo $rowContent['businessname']; ?></td>
<td><?php echo $rowContent['telephoneno']; ?></td>
<td><?php echo $rowContent['emailaddress']; ?></td>
<td><?php echo $rowContent['rating']; ?></td>
</tr>
<?php } ?>
If you are trying to list all active rows, try something like this:
<?php
// Change query to select only acitve rows
$queryContent="SELECT * FROM businesses WHERE active = 'Y'";
$resultContent= $mysqli->query($queryContent);
//while cycle will repeat while sql have results
while($rowContent = $resultContent->fetch_assoc()){
?>
<tr>
<td><?php echo $rowContent['businessname']; ?></td>
<td><?php echo $rowContent['telephoneno']; ?></td>
<td><?php echo $rowContent['emailaddress']; ?></td>
<td><?php echo $rowContent['rating']; ?></td>
</tr><?php } ?>
Php documentation examples should be also usefull.
When you have a list of IDs wich you want to select from sql look at SQL WHERE - IN operator and syntax.
SELECT * FROM businesses WHERE id IN (103, 104, 105)
I could think of two things which can be improved in your code:
instead of select *, you can mention select column1, column2,... which is considered to be the standard
And if you are trying to list only one row, then either access the $rowcontent array with index 0 (or) limit the select query's output rows by using "LIMIT 1" at the end of "SELECT" query (second option valid only if you are not sure about the query whether it will fetch only one row always or not)

Currency Dollar Sign: Better to concatenate in an SQL query, or use PHP?

I heard somewhere that it's better to have the server perform tasks, such as concatenation, but does that also apply to aesthetic stuff as well? How about using FORMAT(val, 2) vs NUMBER_FORMAT(val, 2)?
It seems like double the work, because I will still need to fetch the non-concatenated value(s) to perform other calculations, like getting the sum of all rows.
i.total AS total,
CONCAT('$', FORMAT(i.total, 2)) AS nice_total,
... etc
$sum_total = 0;
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
$sum_total += $row['total']; #calculate sum of all rows
?>
<tr>
<td><?php echo $row['nice_total']; ?></td> <!-- Example 1 -->
</tr>
<?php
}
?>
<tr>
<td>$<?php echo NUMBER_FORMAT($sum_total, 2); ?></td>
</tr>
VS
i.total AS total,
... etc
$sum_total = 0;
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
$sum_total += $row['total']; #calculate sum of all rows
?>
<tr>
<td>$<?php echo NUMBER_FORMAT($row['total'], 2); ?></td> <!-- Example 2 -->
</tr>
<?php
}
?>
<tr>
<td>$<?php echo NUMBER_FORMAT($sum_total, 2); ?></td>
</tr>
I only have 4 fields to fetch with a similar structure (subtotal, tax1, tax2, total), but to fetch the same column twice for concatenation (or even formatting) feels wrong, especially if I have tons of rows; i'm just not sure how to measure the pros/cons. I do like to keep my logic as close together as possible, if that matters.
Thanks!
"It seems like double the work, because I will still need to fetch the non-concatenated value(s) to perform other calculations, like getting the sum of all rows."
Go with your gut here. Why make the DB server work when you can just echo the "$" as you are in your plain HTML? The only thing I that might be wrong with the 2nd approach is that you'll have a "$" printed regardless of whether or not there is an actual value yielded by $row['total'] ...

How to format 1st row in MySQL output differently from all following rows in PHP?

I have a MySQL query that is returning the results that I need correctly. However, I want to clean up the output a bit for my specific use case. Specifically, I'd like to remove a column from the output so that it only appears the first time it's pulled from the database. Here's a quick example of the type of output I'm getting:
Event A - workshop 1
Event A - workshop 2
Event A - workshop 3
Event B - workshop 1
Event B - workshop 3
Event C - workshop 2
Event D - workshop 1
Event D - workshop 2
etc
This is what I'd like instead:
Event A
workshop 1
workshop 2
workshop 3
Event B
workshop 1
workshop 3
Event C
workshop 2
Event D
workshop 1
workshop 2
So, basically, I just want to see the "Event A" title once, even though it's part of the record of workshops.
Here's the php code that I'm working with (in this case, "campaigntitle" is the column I only want to see once per group. "assettitle" would be shown in every row returned by the query) :
<?php do { ?>
<tr>
<td> Details edit delete</td>
<td><?php echo $row_campaignassetjoin['campaigntitle']; ?></td>
<td><?php echo $row_campaignassetjoin['assettitle']; ?></td>
<td><?php echo $row_campaignassetjoin['assettype']; ?></td>
</tr>
<?php } while ($row_campaignassetjoin = mysql_fetch_assoc($campaignassetjoin)); ?>
here's the pertinent mysql query in the document header:
mysql_select_db($database_campaignarchive, $campaignarchive);
$query_campaignassetjoin = "SELECT assets.*, campaign.* FROM campaign JOIN assets ON assets.campaignid=campaign.campaignid ORDER BY campaign.campaignid DESC";
$campaignassetjoin = mysql_query($query_campaignassetjoin, $campaignarchive) or die(mysql_error());
$row_campaignassetjoin = mysql_fetch_assoc($campaignassetjoin);
$totalRows_campaignassetjoin = mysql_num_rows($campaignassetjoin);
First, let me make the requisite observation that you REALLY shouldn't be using the mysql_* functions. You should either be using PDO or mysqli_*
Here's what I would do:
update In order for this to work, your results must be sorted by the campaign title
<?php $lastCampaign = ''; ?>
<?php foreach($rows as $row): ?>
<tr>
<td> Details edit delete</td>
<?php if($lastCampaign != $row['campaigntitle']): ?>
<td><?php echo $row['campaigntitle']; ?></td>
<?php else: ?>
<td> </td>
<?php endif; ?>
<td><?php echo $row['assettitle']; ?></td>
<td><?php echo $row['assettype']; ?></td>
</tr>
<?php $lastCampaign = $row['campaigntitle']; ?>
<?php endforeach; ?>
I haven't tested this, but you get the idea
This is a very common application where you need to group your output by a specific column. There are many ways of doing this. Since you are using PhP, the way to go around doing it is to first make sure that you retrieve the record sorted on "event." Then keep a variable called $old_event and keep comparing it to the event just fetched. If it is different, then output the Event name and set $old_event to the newly fetched event. If not, output only other columns.
You can also use a select with a group by clause, but if you are going to code as explained above, you will not need that... A simple select sorted by event should do.

Categories