How to set variable from MAX and group? - php

I have problem with selecting selecting SQL Max and group syntax then set it to variable. I have no problem from just selecting the MAX score. But Id like to echo the user that own that score and id to redirect to his profile page
This is my Database
-----------------------------
id | user | score | justplayed
1 | player1 | 1000 | 1
2 | player2 | 1000 | 0
PHP code
$sql = "SELECT MAX(score) AS max_score FROM score GROUP BY score WHERE justplayed > 0 ";
$result = mysqli_query($con, $sql);
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
$highscore = $row["max_score"];
$highscoreowner = $row["user"];
$highscoreownerid = $row["id"];
}
}
Html Code
Player of the day
<? echo $highscoreowner; ?>
Score
<? echo $highscore; ?><br>
<a href="profile.php?id=<? echo $highscoreownerid; ?>

You're only selecting the max score in the SQL query, so you can't extract the other values in PHP. If you're looking for the entire row where the score is highest, then use this query instead:
SELECT score, user, id
FROM score
WHERE justplayed > 0
ORDER BY score DESC
LIMIT 1
This will take all the rows, order them from highest to lowest score, and then return only the first row.

Related

Fetch current and next row and compare in a loop

I would like to compare two values from a table:
This is my table:
ID;VALUE
1;700
2;600
3;800
4;900
This is my query:
$stmt = $db->query("SELECT ID, VALUE FROM TABLE);
Now i like to compare the result of the current row with the next row. In mysql it was easy beacause i have to set the row number. I did not find any solution with PDO.
This is my code yet:
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$id = $row["ID"];
$val_current = $row["VALUE"];
$row_next = $stmt->fetch(PDO::FETCH_ASSOC);
$val_next = $row["VALUE"];
if ($val_current > $val_next){
echo "$id is greate!";
}else{
echo "$id is less!";
}
}
The Result is:
1 is greater
3 is less
He missed to check the ID 2 agains ID 3 becaue i fetch the next element in the while loop. So i fetch it to get the next value and i fetch again in the loop. Can i reposition the cursor at the end of the loop?
If you are running MySQL 8.0, this is straight-forward with window function lead():
select
t.*,
(value - lead(value) over(order by id) > 0) is_greater
from mytable t
This gives you a boolean flag called is_greater, with following possible values:
1: this value is greater than the next one
0: this value is smaller than the next one
null: there is no next value
Demo on DB Fiddle:
ID | VALUE | is_greater
-: | ----: | ---------:
1 | 700 | 1
2 | 600 | 0
3 | 800 | 0
4 | 900 | null
In earlier versions, one option is to use a correlated subquery:
select
t.*,
(value - (
select t1.value
from mytable t1
where t1.id > t.id
order by t1.id limit 1
) > 0) is_greater
from mytable t
You just need to remember the previous row and use it in the next iteration pretending it's the current one, whereas the current row will serve as the next one.
$row = null;
while($row_next = $stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row !== null)) {
$id = $row["ID"];
$val_current = $row["VALUE"];
$val_next = $row_next["VALUE"];
if ($val_current > $val_next){
echo "$id is greater!";
}else{
echo "$id is less!";
}
echo "\n";
}
$row = $row_next;
}

PHP/SQL - Add values together if ID is the same in foreach()

I am trying to show statistics for goals scored by players, however sometimes the same player is added to the database with the same playerID, when a player is added twice how can I add the values together to show it as a total, rather than echo the player twice.
db structure example:
playerID | Goals | Season | leagueID
1 5 1 1
2 1 1 1
1 2 1 2
5 3 1 1
1 3 2 2
2 2 2 1
php:
$query = $db->query('SELECT * FROM playerstats ORDER BY goals DESC LIMIT 30');
$num = $query->num_rows;
if($num > 0) {
foreach($query as $row) {
$playerID = $row['playerID'];
$goals = $row['goals'];
echo '
<tr>
<td>'.$playerID.'</td>
<td>'.$goals.'</td>
</tr>
';
}
}
This would show playerID 1, 3 seperate times.
How can I make it show playerID 1 just once with all the goals added together (10)
I have tried changing the query to: SELECT DISTINCT * FROM playerstats ORDER BY goals DESC LIMIT 30 but this made no difference.
Group BY will help you:
<?php
$query = $db->query('SELECT SUM(p.goals) as total_goals,
p.playerID, p.leagueID, p.Season
FROM playerstats as p
GROUP BY p.playerID, p.leagueID, p.Season
ORDER BY total_goals DESC LIMIT 30');
$num = $query->num_rows;
if($num > 0) {
foreach($query as $row) {
echo '
<tr>
<td>'.$row['playerID'].'</td>
<td>'.$row['total_goals'].'</td>
</tr>
';
}
}
Please note, that my query will group also by season and leagues, if you want total goals throughs seasons and leagues, your group by will be:
GROUP BY p.playerID
If you want only the playerID and the sum of the goals not mattering the Season or the leagueID, change your query to:
SELECT DISTINCT playerID AS player,
(SELECT SUM(goals) FROM playerstats WHERE playerID = player) AS totalGoals
FROM playerstats
Well you would group results in array then loop over it. Or sort at SQL level.
Something like this might work:
$playerStats = array();
foreach($query as $row)
{
if(array_key_exists($row['playerID'], $playerStats))
$playerStats[$row['playerID']] += $row['goals'];
else
$playerStats[$row['playerID']] = $row['goals'];
}
// Then loop over playerStats
foreach($playerStats as $playerID => $playerGoals)
}
echo $playerID;
echo $playerGoals;
{

display records after spicific id

Here the SQL query and I need some adjustment to it
SELECT DISTINCT ic.img_path, ic.id
FROM images_community ic
WHERE ic.delete_flag = 0 AND ic.status = 1
ORDER BY ( SELECT (count(id = ic.id ) + ic.views)
FROM image_comments WHERE img_id = ic.id) DESC
I need to show record after specific ID
not limit and offset for sure I need display rows after this id =5
this images retrieve
> images id | img_path
> 1 | dafad.sjdbh
> 2 | dafad.sjdbh
> 5 | dafad.sjdbh
> 3 | dafad.sjdbh
IS there a way to display records after id = 5 in the same query retrieved
You can use limit and offset to achieve it, please see Limit, Offset
If you want all rows after offset just do
SELECT DISTINCT ic.img_path, ic.id
FROM images_community ic
WHERE ic.delete_flag = 0 AND ic.status = 1
ORDER BY ( SELECT (count(id = ic.id ) + ic.views)
FROM image_comments WHERE img_id = ic.id) DESC LIMIT (SELECT cout(*) FROM table_name) OFFSET my_row_offset
Found the row position for this ID and start the Limit from it.

Group together by date, but show all rows

Normally when I group stuff together it is for the obvious use to group together duplicates, but I am making a winners page that shows winners for a bunch of jackpots, some jackpots have 1 winner while other have 3, using GROUP BY date will work if there is only 1 winner but will only show 1 winner when there should be 3.
Here is my code
$result = $db->query("SELECT * FROM r_winners GROUP BY date ORDER BY date DESC");
while($rows = $result->fetch_assoc()){
print"<table class='cashout' style='width:100%;'>
<th colspan='3'>".$rows['jackpot_name']." Winners</th>
<tr>
<td style='width:33%;'>".$rows['winner']."</td><td style='width:33%;'>$".$rows['amount']."</td><td style='width:33%;'>".date("m/d/Y", $rows['date'])."</td></tr>
</tr></table>";
}
It prints out a table like such
---------------------------------------
Daily Jackpot Winners
Username| $5.00 | 12/5/2012 // This table is right, because there is only 1 winner
---------------------------------------
Because there is only 1 winner then GROUP BY really has no affect here
Here is a table for multiple winners
---------------------------------------
Monthly Jackpot Winners
Username | $5.00 | 12/5/2012 // This table is wrong, because there should be 3 winners
---------------------------------------
It needs to look like this
---------------------------------------
Monthly Jackpot Winners
Username | $5.00 | 12/5/2012
Username2 | $2.00 | 12/5/2012
Username3 | $1.00 | 12/5/2012
---------------------------------------
How can I accomplish this?
EDIT: This can maybe explain this better https://gist.github.com/4221167
Just don't use GROUP BY at all. You are already using ORDER BY which will put your dates into logical "groupings".
In response to your comments about ho to output the results in one table, here is how you would need to modify your code.
$result = $db->query("SELECT * FROM r_winners ORDER BY date DESC");
print "<table class='cashout' style='width:100%;'>";
print "<th colspan='3'>".$rows['jackpot_name']." Winners</th>";
while($rows = $result->fetch_assoc()){
print "<tr><td style='width:33%;'>".$rows['winner']."</td><td style='width:33%;'>$".$rows['amount']."</td><td style='width:33%;'>".date("m/d/Y", $rows['date'])."</td></tr>";
}
print "</table>";
Change your query to just use ORDER BY and reformat your loop, placing the table elements outside, and only printing the header once
$result = $db->query("SELECT * FROM r_winners ORDER BY date DESC");
print"<table class='cashout' style='width:100%;'>";
$jackpot_name = '';
while($rows = $result->fetch_assoc()){
if ($jackpot_name != $rows['jackpot_name']) {
$jackpot_name = $rows['jackpot_name'];
print "<th colspan='3'>".$rows['jackpot_name']." Winners</th>";
}
print "<tr><td style='width:33%;'>".$rows['winner']."</td><td style='width:33%;'>$".$rows['amount']."</td><td style='width:33%;'>".date("m/d/Y", $rows['date'])."</td></tr>";
}
print "</table>";
Try removing the GROUP BY and only using ORDER BY.
You should GROUP BY Monthly ORDER BY Winners, of course, if Monthly is unique, then you even don't need to GROUP BY it.
Edit:
After checking your php code, I think you need below:
SELECT
GROUP_CONCAT(winner_name) AS winner_names,
SUM(the_value_column_you_want_to_sum) AS amount
FROM r_winners
GROUP BY date ORDER BY date DESC

details in one Row without any redundancy in the CATID

$query1 = "select *
from linkat_link
where emailuser = '$email2'
or linkname ='$domain_name2'
ORDER BY date desc
LIMIT $From,$PageNO";
id catid discription price
------------------------------------
1 1  domain name 100
2 1  book 50
3 2  hosting 20
4 2  myservice 20
in this script i have one problem , if i have an ID for Each Cantegory , i have some duplicated CATID which has different content but shares the same CATID, i need to make any duplicated CATID to show in one , and all the discription will be in the same line (Cell) on the same row .
So Each CatID will have all the details in one Row without any redundancy in the CATID
Using:
SELECT t.catid,
GROUP_CONCAT(t.description),
GROUP_CONCAT(t.price)
FROM LINKAT_LINK t
WHERE t.emailuser = mysql_real_escape_string($email2)
OR t.linkname = mysql_real_escape_string($domain_name2)
GROUP BY t.catid
ORDER BY t.date DESC
LIMIT mysql_real_escape_string($From), mysql_real_escape_string($PageNO)
...will return:
catid description price
--------------------------------
1 domain name,book 100,50
2 hosting,myservice 20,20
See the documentation for what the GROUP_CONCAT function does.
How to print it to screen using PHP?
Use:
<?php
$query1 = "SELECT t.catid,
GROUP_CONCAT(t.description) AS grp_desc,
GROUP_CONCAT(t.price) AS grp_price
FROM LINKAT_LINK t
WHERE t.emailuser = mysql_real_escape_string($email2)
OR t.linkname = mysql_real_escape_string($domain_name2)
GROUP BY t.catid
ORDER BY t.date DESC
LIMIT mysql_real_escape_string($From), mysql_real_escape_string($PageNO)";
$result = mysql_query($query1);
while($row = mysql_fetch_array($result)) {
echo "CatID:{$row['catid']} <br>" .
"Description : {$row['grp_desc']} <br>" .
"Price : {$row['grp_price']} <br><br>";
} ?>

Categories