Accessing SQL Aliases with PHP - php

This code works to give me what I want in my phpMyAdmin server:
SET #row_number = 0;
SELECT salesperson, units, profit, (#row_number:=#row_number + 1) AS position
FROM sales AS t ORDER BY profit DESC;
The problem happens when I transfer this to php:
<?php
$sql = "SELECT salesperson, units, profit, (#row_number:=#row_number + 1) AS position\n"
. "FROM sales AS t ORDER BY profit DESC";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0){
while ($row = mysqli_fetch_assoc($result))
echo $row['salesperson'] . " " . $row['units'] . " " . $row['profit'] .$row['position'] . "<br>";
}
It outputs the first three rows but not the fourth. The alias created with SQL.

First of all, you choose not exactly the best way to debug your output. Stringifying $row['position'] directly (by piping it into echo) hides a lot of useful info that you would be able to find otherwise.
Second, the query in your second snippet misses actually setting up that variable, like this:
$sql = <<<QUERY
SELECT salesperson, units, profit,
(#row_number:=#row_number + 1) AS position
FROM sales AS t, (SELECT #row_number := 0) AS r
ORDER BY profit DESC
QUERY;
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0){
while ($row = mysqli_fetch_assoc($result)) {
echo "$row[salesperson] $row[units] $row[profit] $row[position]<br>";
}
}

Additionally, in the latest version of MySQL (8.0+) window functions are finally supported which avoids the use of # session variables. Doing so you can also add row numbers by group with PARTITION BY clause:
SELECT salesperson
, units
, profit
, ROW_NUMBER() OVER(ORDER BY profit DESC) AS `overall_position`
, ROW_NUMBER() OVER(PARTITION BY salesperson
ORDER BY profit DESC) AS `salesperson_position`
FROM sales
ORDER BY profit DESC

Related

Check if last 10 rows duplicated

I'm trying to code a php script, which can find if the last 10 rows from mySQL database are the same. And if the values are same, then the script could sent an email.
I can fetch the last 10 rows.
$sql = ("SELECT ID, DayTime,Temperature FROM AllinOne ORDER BY ID DESC LIMIT 10");
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
echo "id: " . $row["ID"]. " - DayTime: " . $row["DayTime"]. " - Temperature " . $row["Temperature"]. "<br>";
}
} else {
echo "0 results";
}
Last 10 results:
Now, I'm trying to check if last 10 rows in "Temperature" column are the same (as we can see).
I use:
$sql2 = "SELECT Temperature, COUNT(*) as duplicates FROM AllinOne GROUP BY Temperature ORDER BY ID DESC LIMIT 10";
$result2 = $conn->query($sql2);
if ($result2->num_rows > 0)
{
// output data of each row
while($row2 = $result2->fetch_assoc())
{
echo $row2["duplicates"]. "<br>";
}
}
but I can't take back the same results (i can't understand the final result).
$row2 results
Could you help me???
Execute the following query and grab the result:
SELECT
COUNT(*) AS count_rows,
MIN(Temperature) AS min_temperature,
MAX(Temperature) AS max_temperature
FROM (
SELECT *
FROM t
ORDER BY DayTime DESC
LIMIT 10
) AS x
Then send an email if count_rows = 10 and min_temperature = max_temperature.
You just need to fix your second query like:
$sql2 = "SELECT Temperature, COUNT(*) as duplicates
FROM (
SELECT ID, DayTime, Temperature FROM AllinOne ORDER BY ID DESC LIMIT 10
) LastData
GROUP BY Temperature";
Here you can test PHP code with queries

group rows, count grouped rows and order by grouped rows

I want to make an analytics system for a website and I am trying to row accesed urls from a db, group by url, count grouped rows and order DESC by number of grouped rows.
$sql = "SELECT COUNT(*) FROM (SELECT DISTINCT url FROM analytic) ORDER by (SELECT DISTINCT url FROM analytic)";
$countQry = mysqli_query($link, $sql);
while($arr = mysqli_fetch_array($countQry)) {
?>
<?=$arr['url']?>
<?
}
?>
thanks
Try using a GROUP BY:
SELECT url, COUNT(url) AS theCount
FROM analytic
GROUP BY url
ORDER BY theCount DESC
Here is PHP code for you to use:
$sql = "SELECT url, COUNT(url) AS theCount FROM analytic GROUP BY url ORDER BY by theCount DESC";
$countQry = mysqli_query($link, $sql);
while ($row = mysqli_fetch_array($countQry, MYSQLI_ASSOC)) {
echo $row['url'], ", ", $row['theCount'];
}

Php number each query result

I am making a leaderboard, I want to number it like 1st place 2nd place etc in a html table field.
How to I number each row of information coming out?
Something like
$result + 1 ?
My query
$result = mysqli_query($con,"SELECT * FROM playerdata WHERE Admin='0' ORDER BY Bank DESC LIMIT 1");
while($row = mysqli_fetch_array($result)) {
$bank = $row['bank'];
}
Thanks.
You can sort through the query results using:
$result = mysqli_query($con,"SELECT * FROM playerdata WHERE Admin='0' ORDER BY Bank DESC LIMIT 900");
$rows = mysqli_num_rows($result);
for($x = 1; $x <= $rows; $x++) {
$row = mysqli_fetch_array($result);
echo "#{$x} " . $row['bank'];
}
This will start counting down, showing "#1... #2... #3..." etc. You can also do this with your while loop:
$result = mysqli_query($con,"SELECT * FROM playerdata WHERE Admin='0' ORDER BY Bank DESC LIMIT 900");
$x = 1;
while($row = mysqli_fetch_array($result)) {
$bank = $row['bank'];
echo "#{$x} " . $bank;
$x++;
}
With query itself you can build the result, I think this is what u needed. Not sure
SELECT #curRank := #curRank + 1 AS rank, a.*
FROM playerdata a, (SELECT #curRank := 0) r
WHERE Admin='0' ORDER BY Bank DESC LIMIT 900
In php
$result = mysqli_query($con,"SELECT #curRank := #curRank + 1 AS rank, a.*
FROM playerdata a, (SELECT #curRank := 0) r
WHERE Admin='0' ORDER BY Bank DESC LIMIT 900");
while($row = mysqli_fetch_array($result)) {
$rank = $row['rank'];
$bank = $row['Bank'];
}

How do I use two mysql tables in one statement

So, I've put in a favourite images table, and I can't figure out how to get it working properly
Basically, this is the setup:
ImageFavs
FavID, UserID, ImgID
ImageList
ImgID, SiteID
I'd like it to select 20 or so images from the favourites table, but only ones that match the siteid in the image list table
This is the code I have at the moment, but it dawned on me it'd select 20 images from favourites, then only display them if the matching site was actually checked.
#select matching sites
for($i=0;$i<count($sites)-1;$i++){
$siteinfo = explode("-",$sites[$i]);
$siteid = $siteinfo[0];
$sitegroup = $siteinfo[1];
$selection[$siteid]="exists";
if($i!=0){
$sqlextra .= " OR ";
}
else{
$sqlextra = "AND (";
}
$sqlextra .= "SiteID='".$siteid."'";
}
if(!empty($sqlextra)){
$sqlextra .= ")";
}
else{
$sqlextra = "AND SiteID='-1'";
}
#show favourites
if($_GET['f']==1){
$sql="SELECT * FROM ImageFavs WHERE UserID='".$_SESSION['User_ID']."' AND Active = '1' ORDER BY RAND() LIMIT 20";
#(rand is just me being lazy, eventually I'll figure out how to separate it onto pages)
$result = mysql_query($sql);
$num = mysql_numrows($result);
if($num>0){
while ($row=mysql_fetch_array($result, MYSQL_BOTH)){
if(empty($sqlextra2)){
$sqlextra2 = " AND (";
}
else{
$sqlextra2 .= " OR ";
}
$sqlextra2 .= "ImgID='".$row['ImgID']."'";
}
$sqlextra2 .= ")";
}
}
#don't show favourites
if(empty($sqlextra2)){
$sqlextra2 = " ORDER BY RAND() LIMIT 20";
}
$sql="SELECT * FROM ImageList WHERE Valid='1' ".$sqlextra.$sqlextra2;
This output $sql from this seems like it could be so much neater though, an example of it is like this
SELECT * FROM ImageList WHERE Valid='1' AND (SiteID='6') AND (ImgID='5634' OR ImgID='8229' OR ImgID='9093' OR ImgID='5727' OR ImgID='7361' OR ImgID='5607' OR ImgID='7131' OR ImgID='5785' OR ImgID='7339' OR ImgID='5849' OR ImgID='7312' OR ImgID='5641' OR ImgID='8921' OR ImgID='7516' OR ImgID='7284' OR ImgID='5873' OR ImgID='8905' OR ImgID='7349' OR ImgID='7392' OR ImgID='8725')
Also, while I'm here, would there be a non resource heavy way to count the number of favourites for a user per website?
It's not for anything big, just messing around on a personal website to see what I can do.
You can INNER JOIN your two tables to get the results you want. INNER is used when you want results from both tables. It's best to use aliases to keep your tables straight.
SELECT l.*
FROM ImageFavs f
INNER JOIN ImageList l ON f.ImgID = l.ImgID
WHERE l.SiteID = [your site ID]
AND f.UserID='" . $_SESSION['User_ID'] . "'
AND f.Active = '1'
ORDER BY RAND() LIMIT 20
To get a count by site you can use GROUP BY. I think this should get you that count
SELECT COUNT(f.ImgID)
FROM ImageFavs f
INNER JOIN ImageList l ON f.ImgID = l.ImgID
WHERE f.UserID='" . $_SESSION['User_ID'] . "'
AND f.Active = '1'
GROUP BY l.SiteID
you want to use "JOIN"
SELECT * FROM ImageFavs LEFT JOIN ImageList ON ImageFavs.ImgID = ImageList.ImgID WHERE ImageList.SiteID = <your_site_id>
This works-
//Assuming $site_id contains the site ID/
$query = "select *.IF from ImageFavs as IF, ImageList as IL where IL.ImgId = IF.ImgId and IL.SiteId = $site_id LIMIT 20"

PHP/MySQL Retrieve the last action of each user to make a list

i m developing a dynamic website but i have a problem with a query. I m trying to build a map dynamically by retrieving date from the database. I enclose the db structure:
countries (code, name)
data (user_id, dateaction, container)
users (user_id, country_code)
I want to display a list of the AVG container for each country, but the average value should be calculated from last action of each user and the data should be submitted the current day. In the case of non-value of "container" for any country the value is 0. I tried many queries but i couldnt achieve the target. I attach some of the queries i tried.
$query = "SELECT AVG(data.container), data.user_id, users.country_code ".
"FROM data, users ".
"WHERE data.user_id = users.user_id AND dateaction >= '".date('Y-m-d').' 00:00:00'."' AND date < '".date('Y-m-d').' 23:59:59'."'".
"GROUP BY users.country_code ";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
$cid=$row['country_code'];
$queryy=mysql_query("select * FROM Countries WHERE country_code='$cid'") or die("Error Occured,plz try again1");
$rowy = mysql_fetch_array( $queryy );
$cname=$rowy['country_name'];
echo '<area title="'.strtoupper($cname).'" mc_name="'.strtoupper($cid).'"></area>'; }
Please may you help me to solve this logical problem?
$query = "SELECT a.user_id, ifnull(a.country_code, 0) as country_code, avg(a.container) ".
"FROM data a INNER JOIN ".
"(SELECT data.user_id, max(dateaction) dateaction ".
"FROM data".
"WHERE dateaction >= '".date('Y-m-d').' 00:00:00'."' AND date < '".date('Y-m-d').' 23:59:59'."'".
"GROUP BY data.user_id) b ".
"ON a.user_id = b.user_id and a.date_action = b.date_action ".
"GROUP BY a.user_id, ifnull(a.country_code, 0) "

Categories