Returning results from every "user" grouped for pagnation of dompdf - php

I have two tables in mysql.
people is an identification table of users.. names/etc
trans is a transaction table, what the users have done (add/subtract balances)
I am wanting to return every "ident" from people, then search trans for that ident's matching rows, and then after all are returned, echo the page break, so each person gets their own page print out. (there shouldn't be so many transactions that a page is not enough..) Also to subquery the balance remaining (trans has both credits and debits, could be positive or negative).
Structure:
people.id #(not queried, unique/auto-increment)
people.name
people.location
people.ident #(assigned number that is same as trans.ident)
trans.id #(not queried, unique/auto-inc)
trans.date
trans.ident
trans.amount
trans.description
Queries:
$query = "SELECT people.ident, people.name, people.location, trans.ident, trans.date, trans.amount, trans.description FROM people LEFT JOIN trans ON people.ident = trans.ident";
$balance = mysql_result(mysql_query("SELECT SUM(amount) FROM trans WHERE ident = $ident", $dblink), 0);
$result = mysql_query($query) or die(mysql_error());
Echo results:
while($row = mysql_fetch_array($result)){
echo $row['name']. " - ". $row['ident']. " - ". $row['amount']. " - " .row['description'];
echo('<div style="page-break-before: always;"></div>');
}
This will print out each transaction, and they are sorted by the ident, but with div after each...
I would like to print out the name and location, also their remaining balance ( once on a div.. and then trans under like so:
<div class="user">['name'] ['location'] $balance</div> #These aren't rows, just a single return
<div class="trans">$row['amount']. " - ". $row['description'];</div>
<div style="page-break-before: always;"></div>
Thanks for any assistance!

Well, that is going to be a little bit difficult because you can not always be sure that the name/location for a person inside the people table is actually for the same person/location. Your database is not completely normalised.
That being said, you can do what you want with a few small changes to your query and some PHP code :)
$query = "SELECT people.ident, people.name, people.location,
trans.ident, trans.date, trans.amount, trans.description
FROM people LEFT JOIN trans ON people.ident = trans.ident
ORDER BY peeople.name, people.location, trans.ident";
Echo results:
$lastName = null;
$lastLocation = null;
while($row = mysql_fetch_array($result)){
if (($lastName !== $row['name']) or ($lastLocation != $row['location'])) {
echo $row['name']. " - ". $row['ident']. " - ". $row['amount']. " - " .row['description'];
$lastName= $row['name'];
$lastLocation = $row['location'];
}
/* ... output the transaction line ... */
echo('<div style="page-break-before: always;"></div>');
}

Related

How to count amount of students per university

I have a SQL database of university students, with the following details:
Table_name: register
Column_names: position, tertinst
The data in the database will look something like this:
Coach..........UCT
Athlete........Tukkies
Official.......University of JHB
Athlete........Tukkies
Athlete........Tshwane Tech
Manager........UCT
I need to count the amount of students who are athletes(position), per university(tertinst) and the output has to be something like this:
UCT.....................735
University of Jhb.......668
Tukkies.................886
this is my attempt:
$positionx = 'Athletes';
include_once 'core/includes/db_connect.php';
$sql = "SELECT tertinst, COUNT(position) FROM register WHERE position = '$positionx' GROUP BY tertinst ";
$result = $conn->query($sql);
while ($row = mysql_fetch_array($result)) {
echo $row['COUNT(tertinst)'] . '......' . $row['COUNT(position)'];
}
$conn->close();
I get no result when the code is executed and I have searched for a different solution for hours, without success.
I made a few mistakes, and corrected the syntax in the sql count, as well as the echo. Here is the solution to my problem:
<?php
include_once 'core/includes/db_connect.php';
$sql = "SELECT tertinst, COUNT(*) total FROM register WHERE position = 'Athletes' GROUP BY tertinst ";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
$tertinst = $row["tertinst"];
echo $tertinst . '......' . $row['total'] . '<br>';
}
$conn->close();

Fixing performance issues when looping through MySQL results in PHP

I'm working on a virtual game board style game in which players get points on a certain area of the board. (Take it easy on me now as I only do this as a hobby so I might be doing this in the worst way possible)
I have 3 tables. One stores all the player information (eg. id, screenname). A second stores all the Area information (eg. id, x, y) and a third stores how many points each player has in each area (eg. id, playerid, areaid, points). In order to create a "leaderboard" I'm looping through all the players, then within that loop I'm also looping through all the areas, then finally within that second loop, I get the leader of that area and see if that matches the current player in the first loop, if so I increment a counter, then store it into an array. (See code below with some commenting)
I looked into MySQL caching, but I dont have access to a lot of the server options, as well as would like to keep as much of the results as live as possible, so caching may not be the right way to go.
My question is whether or not I'm doing this properly. Currently there is only around 10 players, and approx. 500 areas. I'm finding the below script already takes about 5-8 seconds to run. Potentially there could be millions of areas, so such a long delay in processing could be catastrophic (for the leaderboard anyway). Am I going about this the right way, and/or is there a better way to do this?
<?php
$leaders = array();
//Loop through all the players
$sql = "SELECT * FROM players";
$result = mysqli_query($con, $sql) or die(mysqli_error($con));
while ($row = mysqli_fetch_array($result)) {
//save player information into variables
$playerId = $row['id'];
$playerScreenName = $row['screenname'];
//Reset the area counter
$AreaCount = 0;
$leader = array();
//Loop through all areas
$sql2 = "SELECT * FROM areas";
$result2 = mysqli_query($con, $sql2) or die(mysqli_error($con));
while ($row2 = mysqli_fetch_array($result2)) {
$areaId = $row2['id'];
//Get the player with the most points in that area
$sql3 = "SELECT * FROM points WHERE areaid='$areaId' ORDER BY totalpoints DESC LIMIT 1";
$result3 = mysqli_query($con, $sql3) or die(mysqli_error($con));
while ($row3 = mysqli_fetch_array($result3)) {
$leaderOfArea = $row3['playerid'];
//See if the leader of the area is the same player we are looping through
if ($playerId == $leaderOfArea) {
//if it is, then increment the counter
$AreaCount++;
}
}
}
//Store the leader information into an array to be output later
$leader['screenname'] = $playerScreenName;
$leader['areacount'] = $AreaCount;
$leaders[] = $leader;
}
// sort leaders by score
usort($leaders, 'compare_areacount');
?>
There is overhead of opening database connections, and when you do it in a loop, you exacerbate the problem (and then when you add a loop inside of that, you make it that much worse). Instead, restructure it as one query using a Join or Subquery.
This post has some specifics.
I think this code can help. You might have to change the sql queries with appropriate column names you need.
<?php
$leaders = array();
//Loop through all the players
$sql = "SELECT * FROM players";
$result = mysqli_query($con, $sql) or die(mysqli_error($con));
$players = array();
while ($row = mysqli_fetch_array($result)) {
//save player information into variables
$players[$row['id']] = array($row['screenname'], 0);
// number 0 will be the count of how many times this player is the leader
}
$sql = "SELECT Area.id, Area.name, (SELECT Pts.playerid FROM `points`"
. " AS Pts WHERE Pts.areaid=Area.id ORDER BY totalpoints"
. " DESC LIMIT 1) AS `leader_id` FROM `areas` AS Area";
$result = mysqli_query($con, $sql) or die(mysqli_error($con));
$areas = array();
while ($row = mysqli_fetch_row($result)) {
$areas[$row[0]] = $row;
// $row[2] will contain leader_id
// index 1 corresponds to the second element in player values array
$players[$row[2]][1]++;
}
// now if you want to print:
foreach ($areas as $area_id => $area) {
echo "Area id: " . $area_id . ", name: " . $area[1] . ", leader_id: " . $area[2] . "<br /><br />";
}
foreach ($players as $player_id => $player) {
echo "Player id: " . $player_id . ", name: " . $player[0] . ", No of areas this player is a leader of: " . $player[1] . "<br /><br />";
}

How can i simplify this php mysql count code and reduce queries?

I have database with 8 different product category for download.
pic, app, ebo, tem, des, cod, mus, cat
I'd like to count clients total downloaded products and total downloads of each product category.
Maximum daily limit downloads for category product is 3.
When user log in should see how many downloads remain.
Here is working code
$query = "SELECT COUNT(*) as sum FROM service_downloads where client_id like '$client'";
$result = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result))
{
echo "You have downloaded". $row['sum'] ." products.";
echo "<br />";
}
$query = "SELECT COUNT(*) as sum FROM service_downloads where client_id like '$client' and product like 'pic'";
$result = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result))
{
echo "". $row['sum'] ." downloaded pictures";
$leftovers = 3 - $row['sum'];
echo " $leftovers pictures remain for download";
echo "<br />";
}
$query = "SELECT COUNT(*) as sum FROM service_downloads where client_id like '$client' and product like 'app'";
$result = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result))
{
echo "". $row['sum'] ."downloaded applications";
$leftovers = 3 - $row['sum'];
echo " $leftovers applications remain for download.";
echo "<br />";
}
$query = "SELECT CO.... This procedure repeat eight times for different product category.
result
You have downloaded 12 products.
3 downloaded pictures 0 pictures remain for download.
1 downloaded applications 2 applications remain for download.
3 downl.......
You could use a GROUP BY statement to group your results.
SELECT COUNT(`Product`) AS `Sum`, `Product`
FROM `service_downloads`
WHERE `client_id` = '<client_id>'
GROUP BY `Product`
Then you can use one while statement to loop through each product:
// Print out result
while($row = mysql_fetch_array($result))
{
echo "". $row['Sum'] ."downloaded " . $row['Product'];
$leftovers = 3 - $row['Sum'];
echo " $leftovers " . $row['Product'] . " remain for download.";
echo "<br />";
}
$query = "SELECT COUNT(*) as sum,product FROM service_downloads where client_id like '$client' GROUP BY product";
$result = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result))
{
echo "You have downloaded". $row['sum'] ." ".$row['product'];
echo "<br />";
}
This should work
You should breakdown the quantity of downloads per category in one query:
SELECT product,COUNT(*)
FROM service_downloads
WHERE client_id like '$client';
I also don't think you need to use LIKE; you probably want to use =
You can get a single result set with all the sums in it with this query.
SELECT COUNT(*) as sum, product
FROM service_downloads
WHERE client_id = '$client'
AND PRODUCT IN ('pic', 'app', 'abc', 'def', 'ghi')
GROUP BY product WITH ROLLUP
ORDER BY product NULLS FIRST
This will give you one row for each specific product and a summary (rollup) row with a NULL value in the product column.
If this query takes a long time create an index on (client, product) and it should go pretty fast.
If you are showing this data frequently, which is what it sounds like, then you should have a separate table that represents those SUMs and is index by CLIENT_ID.
You can then increment/decrement that value each time you add a new entry.
For example, when you add a new row to service_downloads with an entry in 'pic' for CLIENT_ID 1, then you would also increment this shortcut table:
UPDATE service_counts SET pic=pic+1 WHERE client_id=1;

MySQL/PHP Count

I have 2 MySQL tables, one for storing albums and the other for songs. I am displaying a list of albums in a table, and I want to be able to add a column called songs to display the number of songs in this album. The way I have it now just messes up my table:
Thanks for everyone's help!
Assuming that "playlist" is what you consider an album and the first while loop iterates on playlists, I'd rewrite your code like this:
while($row = mysql_fetch_array($rs)) {
echo "<tr>\n";
echo "<td>".$row['playlist_id']."</td>";
// Assuming playlist_id is an integer value in your database
$query = "
SELECT Playlist_id, COUNT(Playlist_id) AS songCount
FROM ws_music
WHERE Playlist_id = ". intval ($row['playlist_id']) ."
GROUP BY Playlist_id
";
$result = mysql_query($query) or die(mysql_error());
// No need for the second while loop
$row2 = mysql_fetch_array($result);
echo "<td>There are ". $row2['songCount'] ." ". $row2['Playlist_id'] ." song.</td>";
echo "</tr>";
}

Duplicate ticket number in mysql

I want to find if there are any duplicate ticket number in my table.
my code below is displaying the first ticket number from classes table which is 1039, I want to diplay if there is a duplicate. 1039 is NOT a duplicate. what is my problem?
$query = "SELECT ticket, COUNT(ticket) AS NumOccurrences FROM classes GROUP BY ticket HAVING (COUNT(ticket) > 1)";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result))
{
$ticket = $row['ticket'];
}
if($result)
{
echo $ticket. "<br/>";
echo "there are " . mysql_num_rows($result) . " tickets ";
}
else
{
echo "no duplicate ";
}
You need a GROUP BY clause, otherwise you're counting all tickets.
SELECT ticket, COUNT(*) c FROM classes GROUP BY ticket HAVING (c > 1)
Try
SELECT ticket, COUNT(ticket) as `count` FROM classes GROUP BY ticket WHERE `count` > 1

Categories