Sorting individually calculated results from mysql in php - php

Currently for a football league, standings are calculated with their own table so I have to manually input/edit Wins, losses, ties, PF and PA. I want to generate this dynamically based on the results of the schedule table which is where scores are recorded.
So I have the following ugly code:
$teamidsql = mysql_query("select team_id, count(team_id) as numteams from team WHERE league_id=$currentleague AND team_div='$div'");
$teamid = mysql_result($teamidsql,0,"team_id");
$numteams = mysql_result($teamidsql,0,"numteams");
$endteams = $teamid+$numteams;
while($teamid < $endteams)
{
$result2=mysql_query("select team_name, team_div,
count(case when (schedule_team1_id = $teamid and schedule_team1_score > schedule_team2_score) or (schedule_team2_id = $teamid and schedule_team2_score > schedule_team1_score) then 1 else NULL end) as wins,
count(case when (schedule_team1_id = $teamid and schedule_team1_score < schedule_team2_score) or (schedule_team2_id = $teamid and schedule_team2_score < schedule_team1_score) then 1 else NULL end) as losses,
count(case when schedule_team1_score = schedule_team2_score then 1 else NULL end) as ties,
sum(case when schedule_team1_id = $teamid then schedule_team1_score else schedule_team2_score end) as pf,
sum(case when schedule_team1_id <> $teamid then schedule_team1_score else schedule_team2_score end) as pa
from schedule, team
where team_id = $teamid AND team.team_div='$div' AND schedule_week >= 1 and schedule_week <= 13 and schedule.league_id = $currentleague and (schedule_team1_id = $teamid or schedule_team2_id = $teamid)") or die(mysql_error());
$t_n = mysql_result($result2,0,"team_name");
$t_w = mysql_result($result2,0,"wins");
$t_l = mysql_result($result2,0,"losses");
$t_t = mysql_result($result2,0,"ties");
$t_pf = mysql_result($result2,0,"pf");
$t_pa = mysql_result($result2,0,"pa");
echo "<tr>";
echo "<td>$t_n</td><td>$t_w</td><td>$t_l</td><td>$t_t</td><td>$t_pf</td><td>$t_pa</td>";
echo "</tr>";
$teamid++;
}
Which currently generates the following html:
http://i.stack.imgur.com/sBVfM.png
My question is how can I sort it? The old table was easy, but I have no idea how I would take this individual data I'm calculating and then sort it via wins, losses, ties, pf then pa.

datatables is the fastest solution to this problem. Give the table a class, call datatabes in the onload, and it will render javascript sorting based on the contents of the html.
http://datatables.net/

Related

How to fetch data from Database table by using MySQL query

Currently, I'm stuck here in this part of my program. I want to fetch the data from the table I created which named enrollment_confirm. I want to add the total of female students and male students then the total combined of the two gender.
Here is my code so far in MySQL.
include_once('samplesf1-db.php');
$pdo = Database::connect();
$query1 = "SELECT
COUNT(CASE WHEN UPPER(Gender) = 'TOTAL MALE' THEN 1 END) Male,
COUNT(CASE WHEN UPPER(Gender) = 'TOTAL FEMALE' THEN 1 END) Female,
COUNT(CASE WHEN Gender IS NULL THEN 1 END) 'Not Assigned',COUNT(LRN) AS 'COMBINED' FROM enrollment_confirm";
$result = mysqli_query($con, $query1);
while($row = mysqli_fetch_array($result)){
echo $row['Gender'];
}
Database::disconnect();
?>
Is there anything
So, when I run the code. This is what it says.
enter image description here
Can you tell me if I did something wrong in the query?

Echo value and percentage from SQL server Union query in PHP

I have an issue where I'm trying to find the percentage of two queries but want to retain the session value to echo elsewhere. let me explain.
My first union query returns a value E.G. 100
$sql1 = "select COUNT(*) From
(select inc.INCIDENT_NUMBER as TICKET
From dbo.HELP_DESK as inc
Where inc.STATUS < 3
and inc.ASSIGNED_GROUP = 'Scheduling'
UNION ALL
SELECT chg.INFRASTRUCTURE_CHANGE_ID AS TICKET
FROM dbo.CHANGE as chg
WHERE chg.CHANGE_REQUEST_STATUS NOT IN (1,4,5,8,9,10,11,12)
and chg.ASGRP in = 'Scheduling') num1";
I then want to echo the result as a session value so:
$SCH = sqlsrv_query($conn,$sql1);
if( $SCH === false) {
die( print_r( sqlsrv_errors(), true) );
}
while( $Row = sqlsrv_fetch_array( $SCH, SQLSRV_FETCH_NUMERIC) ) {
$_SESSION['$SCH'] = $Row[0];
}
so far so good. However, I want to calculate the percentage based on my second union query.
$sql2 = "select COUNT(*) From
(select inc.INCIDENT_NUMBER as TICKET
From dbo.HELP_DESK as inc
Where inc.STATUS < 4
and inc.ASSIGNED_GROUP = 'Scheduling'
UNION ALL
SELECT chg.INFRASTRUCTURE_CHANGE_ID AS TICKET
FROM dbo.CHANGE as chg
WHERE chg.CHANGE_REQUEST_STATUS < 9
and chg.ASGRP = 'Scheduling') num2"
The second value is 250 as an example. So I'm trying to calculate the percentage e.g. (100/250) * 100 = 40%
function percentage ($sql1,$sql2)
{
return ($sql1/$sql2) * 100;
}
Echo percentage
The last bit pulls back nothing, blank screen. There's probably a much easier way of doing this and given my relative php newcomer status, I'm probably mixing up several functions at once.
I'd appreciate a little help getting it working. Thanks for taking the time to read.
Managed to resolve the percentage issues, can output seperate session values.
select
s.activeCount * 100 / s.totalCount as Percentage
FROM
(select activecount = (select COUNT(*) From
(select inc.INCIDENT_NUMBER AS TICKET
From dbo.HELP_DESK as inc
Where inc.STATUS < 3
and inc.ASSIGNED_GROUP = 'Scheduling'
UNION ALL
SELECT chg.INFRASTRUCTURE_CHANGE_ID AS TICKET
FROM dbo.CHANGE as chg
WHERE chg.CHANGE_REQUEST_STATUS NOT IN (1,4,5,8,9,10,11,12)
and chg.ASGRP = 'Scheduling') num),
totalCount = (select COUNT(*) From
(select inc.INCIDENT_NUMBER AS TICKET
From dbo.HELP_DESK as inc
Where inc.STATUS < 4
and inc.ASSIGNED_GROUP = 'Scheduling'
UNION ALL
SELECT chg.INFRASTRUCTURE_CHANGE_ID AS TICKET
FROM dbo.CHANGE as chg
WHERE chg.CHANGE_REQUEST_STATUS < 9
and chg.ASGRP = 'Scheduling') num)) s

mysql ranking for a single user

Im using a suggestion from Daniel Vassallo here to rank entries in my mysql table.
The suggestion doesn't deal with ties and thats the way I want it as a newer entry does not get a higher rank than an older entry with the same score on my scoreboard that way and it works for my needs.
My problem is that I want to be able to use this type of ranking to get the ranking for a single user. So from the output of this query I would like to define a name so that the script returns the rank, name and score of only that user.
I have tried a lot of different methods and as some of them deal with ties the results for a single user end up different from what is displayed in the results of the code below.
Your help would be greatly appreciated....going grey over this!
this is my current code:
it currently outputs:
rank name score
me 1111
me 1111
you 1110
<?php
include("common.php");
$link=dbConnect();
$limit = safe($_POST['limit']);
$query = "SELECT name, score, #curRank := #curRank + 1 AS rank
FROM $dbName . `scores`, (
SELECT #curRank := 0
) q
ORDER BY score DESC LIMIT $limit";
$result = mysql_query($query);
$my_err = mysql_error();
if($result === false || $my_err != '')
{
echo "";
}
$num_results = mysql_num_rows($result);
for($i = 0; $i < $num_results; $i++)
{
$row = mysql_fetch_array($result);
echo $row[rank] . " ". $row['name'] . " - " . $row['score'] . "\n";
}
?>
UPDATE
To clarify on ties; the original script will always increment regardless of ties this is how I want it to be because I don't want it so ties are ranked the same (no joint places) and it just so happens the script will favour the first person to achieve the score so that a new player can't knock him/her off the top spot with the same score, they have to beat it.
I know this is deprecated as I have seen in allot of similar posts but I'm just trying to get the skeleton built before I add the meat to the bones.
As kindly suggested by Spencer7593 I have tried the following code without much luck so far.
<?php
include("common.php");
$link=dbConnect();
$limit = safe($_POST['limit']);
$query = "SELECT name, score, #curRank := #curRank + 1 AS rank
FROM $dbName . `scores`, (
SELECT #curRank := 0
) q
ORDER BY score DESC LIMIT $limit";
$result = mysql_query($query);
$my_err = mysql_error();
if($result === false || $my_err != '')
{
echo "";
}
$num_results = mysql_num_rows($result);
while ($row = $result->fetch_assoc()) {
if ( $row['rank'] == 'you' )
{
// output this row because it's for the specified user
echo $row['name'];
}
else
{
continue;
}
}
?>
To get rankings for a single user extracted from the query results, you could run through the results in PHP, just like you are doing, but "skip" the output of rows that aren't for the specified user.
There's no need for a for ($i=0;i< loop. Use a "while fetch" loop. (I'm loathe to give you any example code using the deprecated mysql interface; new development should use either mysqli or PDO.)
while ($row = $result->fetch_assoc()) {
if ( $row['name'] == 'you' ) {
// output this row because it's for the specified user
echo $row['rank'];
} else {
// skip this row
}
}
You make some noise about handling "ties", but what's not clear what you actually want as output. If you want rows that have the same value for "score" have the same value for rank, just handle that in your query. If the score on the current row matches the score from the previous row, don't increment the rank. e.g.
SELECT #curRank := IF(s.score=#prev,#curRank,#curRank + 1) AS rank
, s.name
, #prev := s.score AS score
FROM $dbName . `scores` s
CROSS
JOIN (SELECT #curRank := 0, #prev := NULL) q
ORDER BY s.score DESC
LIMIT $limit
Including potentially unsafe values into the SQL text leads to SQL Injection vulnerabilities; we're going to assume that you've guaranteed the values of $dbName and $limit are safe.
If you want the query to filter out rows for a particular name, then wrap that query in parens and reference it as an inline view, e.g.
SELECT v.rank
, v.name
, v.score
FROM ( SELECT #curRank := IF(s.score=#prev,#curRank,#curRank + 1) AS rank
, s.name
, #prev := s.score AS score
FROM $dbName . `scores` s
CROSS
JOIN (SELECT #curRank := 0, #prev := NULL) q
ORDER BY s.score DESC
LIMIT $limit
) v
WHERE v.name = 'you'
ORDER BY v.rank ASC

Mysql only outputs last loops data

i am trying to output statistics of calls made by agents across all dialing campaigns called for the day. there are multiple campaigns, currently 3, dialed in a day. I get the campaign data from a table name that changes by campaign like so custom_16546546 and custom_1564654. I run a query to get the numeric part of the column name then pass that as a variable in to another query that outputs the users statistics. This is where it only displays data from what i can tell is the last query loops information. I have displayed the array data from the first query to confirm the table names are being stored and it looks fine.
$today = "2013-05-29";
$customquery = "SELECT distinct( entry_list_id) FROM vicidial_list where entry_list_id > 0 and last_local_call_time between '$today 00:00:00' and '$today 23:59:59';" ;
$customresult = mysql_query($customquery) or die(mysql_error());
$customrows = mysql_num_rows($customresult);
while ($customrowResult = mysql_fetch_array($customresult))
{
$customID[] = $customrowResult["entry_list_id"];
}
$z = 0;
if(!$customID){
//echo " Please Select a valid date range: ".$today. " - ".$today." is not valid" ;
}else{
while($z<$customrows)
{
$query = "SELECT
vicidial_users.user,
vicidial_users.full_name,
vicidial_log.list_id,
COUNT(CASE WHEN (vicidial_log.status = 'SALE') THEN 1 ELSE null END) as sumcountSamnt,
COUNT(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].up_amt <> '') THEN 1 ELSE null END) as sumcountupAmnt,
COUNT(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].cc_num <> '') THEN 1 ELSE null END) as sumccverifiedcountAmnt,
COUNT(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].bank_act <> '') THEN 1 ELSE null END) as sumbankverifiedcountAmnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].cc_num <> '') THEN custom_$customID[$z].s_amount ELSE null END) as sumccverifiedAmnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].bank_act <> '') THEN custom_$customID[$z].s_amount ELSE null END) as sumbankverifiedAmnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].d_amt ELSE null END) as sumDamnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].up_amt ELSE null END) as sumUpamnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].md_amt ELSE null END) as sumMdamnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].s_amount ELSE null END) as sumSamnt
FROM
vicidial_log
INNER JOIN
vicidial_users
ON
(vicidial_log.user = vicidial_users.user)
INNER JOIN
custom_$customID[$z]
ON
(vicidial_log.lead_id = custom_$customID[$z].lead_id)
WHERE
call_date
BETWEEN
'$today 00:00:00'
AND
'$today 23:59:59'
AND
vicidial_log.user != 'VDAD'
AND
vicidial_users.user_group != 'TX-Training'
GROUP BY
vicidial_log.user, vicidial_log.campaign_id
";
//This query is used to sum loop data data
$queryResult = mysql_query($query) or die(mysql_error()); //This line perfomrs query error handling
$z++;
}
here is a snippet of how the data is displayed
$result = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_assoc($result))
{
echo "<tr>\n";
//--fullname and userID
echo "<td> ".$row["full_name"]. " - ".$row["user"]."</td>\n";
//Agent total sales amount
if ($row["sumcountSamnt"] == '0') {
echo "<td>$nosalestxt</td>\n";
} else {
echo "<td> $".$row["sumSamnt"]."</td>\n";
}
}
So i want to be able to display a sum total of data for each user from all the campaigns they dialed from.
Thanks in advance for your help
EDIT: i use &row from a while loop to output the data and yes Chris i would like to store it an array, but i guess im just missing it, thanks again
Based on the code snippets you have given it looks like you are overwriting the value of $queryResult after each execution of the loop. Perhaps you meant to execute the query and put the results into an array (or something similar) to loop over and display later.
Also I notice you reference $row[] in your output, how are you assigning a value to that variable?

Displaying 11 consecutive rows from a query where middle row contains a variable

On my web page, there is a variable called $submission. I would like to display exactly 11 rows from the query below: the row where $submission equals $row["title"], 5 rows above it, and 5 rows below it. All ranked by points descending.
How can I do this?
$sqlStr = "SELECT title, points, submissionid
FROM submission
ORDER BY points DESC";
$result = mysql_query($sqlStr);
$arr = array();
$count=1;
echo "<table class=\"samplesrec\">";
while ($row = mysql_fetch_array($result)) {
echo '<tr >';
echo '<td>'.$count++.'.</td>';
echo '<td class="sitename1">'.$row["title"].'</td>';
echo '<td class="sitename2"><div class="pointlink2">'.number_format($row["points"]).'</div></td>';
echo '</tr>';
}
echo "</table>";
This is a little tricky if several rows share the same value for "points":
points | title | submissionid
------ + ----- + ------------
...
50 | 'foo' | ABCD01234 <-- If (50, 'foo') is the "midpoint" record,
50 | 'bar' | EF7654321 <-- does (50, 'bar') come before or after?
...
In this case, we need to impose an order. For convenience we're going to order by "points" descending and then "title" descending.
Assuming your "midpoint record" has a points value of '#points' and a title '#title', we'll say the records that come "before" the midpoint are those records whose (points, title) > (#points, #title). Similarly, those records "after" the midpoint have their (points, title) < (#points, #title).
Putting it together, we have:
-- First, initialize user variables with the points and
-- title of our midpoint (including midpoint)
--
SELECT #title := title,
#points := points
FROM submission
WHERE title = ? -- bind your $submission variable bere
LIMIT 1;
-- Now, select six records greater than or equal to our
-- midpoint.
--
SELECT title, points, submissionid
FROM ( SELECT title, points, submissionid
FROM submission
WHERE (points, title) >= (#points, #title)
ORDER BY points ASC, title ASC
LIMIT 6) gte
-- and UNION those records with five records less than
-- our midpoint
--
UNION
SELECT title, points, submissionid
FROM ( SELECT title, points, submissionid
FROM submission
WHERE (points, title) < (#points, #title)
ORDER BY points DESC, title DESC
LIMIT 5) lt
-- Finally sort the result set
--
ORDER BY points DESC, title DESC
You need to use a UNION
(
SELECT title, points, submissionid
FROM submission
WHERE points < (SELECT points FROM submission WHERE title = <row_title> LIMIT 1)
ORDER BY points DESC LIMIT 5
)UNION(
SELECT title, points, submissionid
FROM submission
WHERE points > (SELECT points FROM submission WHERE title = <row_title> LIMIT 1)
ORDER BY points ASC LIMIT 5
) ORDER BY points DESC
I haven't tested it, but this is the gist of it. You will get 10 records (or less), you'll have to figure out in PHP which records should go above your $submission and which below, since if you get 9 records you wont know if 4 are higher, or 5.
Alternatively you could just do it with 2 queries of course >_>
SELECT
title, points, submissionid
FROM
submission
WHERE
ROWID >= (SELECT ROWID FROM submission WHERE ..... ORDER BY points DESC) - 5
AND
ROWID <= (SELECT ROWID FROM submission WHERE ..... ORDER BY points DESC) + 5
ORDER BY
points DESC
I think that the following might do what you are asking. It will run the query and start reading records from the result set up until it finds the first occurrence of a record with a title that equals the $submission variable that you have (if I understand it correctly the primary key of your table is the submissionid and the title is a simple field - i.e. you do not have a unique key on it, so there may be more than one records with the same title).
After it finds that first record it will read 5 more records and stop. Then it will provide you with the part of the array of records that you wish to print and finally it will print it.
$sqlStr = "SELECT title, points, submissionid FROM submission ORDER BY points DESC";
$result = mysql_query($sqlStr);
$count = 1;
$found = false;
$continue = true;
$records = array();
$row = mysql_fetch_array($result);
while ($row !== false && $continue === true)
{
if($found == false && $row['title'] == $submission)
{
$found = true;
}
elseif($found == true && $count < 6)
{
$count++;
}
elseif($found == true && $count >= 6)
{
$continue = false;
}
$records[] = $row;
$row = mysql_fetch_array($result);
}
if($found === true)
{
if(array_count($records) > 11)
$records = array_splice($records, -11);
}
else
{
$records = array();
}
echo "<table class=\"samplesrec\">";
for($i = 1; $i <= count($records); $i++)
{
echo '<tr >';
echo '<td>'.$i.'.</td>';
echo '<td class="sitename1">'.$records[$i]["title"].'</td>';
echo '<td class="sitename2"><div class="pointlink2">'.number_format($records[$i]["points"]).'</div></td>';
echo '</tr>';
}
echo "</table>";
If there are no duplicate "title" values and if there are no duplicate "points"
SELECT title, points, submissionid
FROM submission
WHERE points <=
( SELECT points
FROM submission
WHERE points >=
( SELECT points
FROM submission
WHERE title = #row_title
)
ORDER BY points ASC
LIMIT 1 OFFSET 5
)
ORDER BY points DESC
LIMIT 11 OFFSET 0
I think its simplest to just do 2 queries against the database, but you could do it in PHP:
$entryFound = false;
$counter = 0;
$priorEntries = array();
while ($row = mysql_fetch_array($result)) {
$rowHtml = '<tr >';
$rowHtml .= '<td>'.$count++.'.</td>';
$rowHtml .= '<td class="sitename1">'.$row["title"].'</td>';
$rowHtml .= '<td class="sitename2"><div class="pointlink2">'.number_format($row["points"]).'</div></td>';
$rowHtml .= '</tr>';
if ($entryFound) {
if ($counter < 5) {
$counter++;
echo $rowHtml;
}
} else {
array_unshift($priorEntries, $rowHtml);
if (strcmp($row["title"], $submission) == 0) {
echo implode(array_reverse($priorEntries));
$entryFound = true;
}
array_splice($priorEntries, 5);
}
}
If the intention is to use single query and table is small and performance doesn't matters then use
SELECT b.title, b.points FROM (
SELECT #rank1 := #rank1 + 1 as slno, temp1.* FROM (
SELECT s1.title, s1.points, COUNT(s2.title) rank
FROM submission s1
JOIN submission s2 ON s1.points <= s2.points
GROUP BY s1.title, s1.points
ORDER BY rank, s1.title ASC
) as temp1
JOIN( SELECT #rank1 := 0 ) AS init
ORDER BY slno
) a
LEFT JOIN (
SELECT #rank2 := #rank2 + 1 as slno, temp1.* FROM (
SELECT s1.title, s1.points, COUNT(s2.title) rank
FROM submission s1
JOIN submission s2 ON s1.points <= s2.points
GROUP BY s1.title, s1.points
ORDER BY rank, s1.title ASC
) as temp1
JOIN( SELECT #rank2 := 0 ) AS init
ORDER BY slno
) b ON a.slno BETWEEN b.slno - 5 AND b.slno + 5
WHERE a.title = <row_title>;
This will return the row selected by and upto 5 above(if present) and upto 5 below(if present).
However, it is highly suggested to use temporary table to store ranks and the use it to display ranks.
More details about above query #
http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#460
More details about optimized method #
http://onlamp.com/pub/a/mysql/2007/03/01/optimize-mysql-rank-data.html

Categories