I'm reporting my question to be a little more succinct. (deleted other)
I have a time reporting system I have built, and I am trying to create an adherence type report.
Esentially I'm trying to do the following:
Gather all unique names ($fn, $ln) in my database, based on a where clause and the fields practice=ccv & year=2016 (for example)
Then I also want to gather up another list of names ($fn, $ln), based on practice=ccv & year=2016 and additional where clause week=8
This will give me 2 DISTINCT lists that I can compare, and the difference will be the Outstanding timecards for week 8.
From there, I need to display all the names for submitted (from #3 above) and also the list of outstanding (by comparing the #1 and #2 above)
Thus far, I can get the list of names. However, I then need to display them with additional data from the database for each person (Region, Timestamp, etc ..)
Desired Output would be something like this:
Submitted
EMEA
John J
Wally R
North America
Davis D
Bob C
John Y
Outstanding
EMEA
Kyle D
North America
Cory T
Hugh R
John J
LATAM
etc ....
Thus far, here is what I have .. I'm sure I'm going about this the wrong way.
<?php
$con = mysqli_connect("localhost","xxx","xxx!","xxx");
//Get distinct names from practice
if ($con) {
$SQL = "SELECT DISTINCT fn,ln FROM $table WHERE year='$year' AND practice='$practice' AND archived!='yes' ORDER BY region,fn,ln";
}
$result = mysqli_query($con,$SQL);
if (!$result) die('Couldn\'t fetch records');
while ( $db_field = mysqli_fetch_assoc($result) ) {
$name[] = trim($db_field['fn']. " " .$db_field['ln']);
}
//Get distinct names for current week practice
if ($con) {
$SQL2 = "SELECT DISTINCT fn,ln FROM $table WHERE year='$year' AND week_num='$week' AND practice='$practice' AND archived!='yes' ORDER BY region,fn,ln";
}
$result2 = mysqli_query($con,$SQL2);
if (!$result2) die('Couldn\'t fetch records Again');
while ( $db_field = mysqli_fetch_assoc($result2) ) {
$name2[] = trim($db_field['fn']. " " .$db_field['ln']);
}
//$SQL3 = "SELECT fn,ln,week_start_date,region FROM $table WHERE fn IN ( '".implode("', '", $differences)."' )");
mysqli_close($con);
?>
<TABLE><TR><TD>
<B>All Names</B><BR>
<?php
foreach ( $name as $item ) {
echo $item . "<br/>";
}
?>
</TD>
<TD>
<B>Names for Week 8</B><BR>
<?php
foreach ( $name2 as $item2 ) {
echo $item2 . "<br/>";
}
?>
</TD>
<TD>
<B>Outstanding</B><BR>
<?php
$results = array_diff($name, $name2);
foreach($results as $val) {
echo $val ." - ".$val2."<BR>";
}
?>
</TD>
</TR>
</TABLE>
I think you should solve this at MySQL level.
// All names with all data
$SQL = "SELECT DISTINCT *, CONCAT(fn,' ',ln) AS `name` FROM $table WHERE year='$year' AND practice='$practice' AND archived!='yes' ORDER BY region,fn,ln";
// Names for specific week with all data
$SQL = "SELECT DISTINCT *, CONCAT(fn,' ',ln) AS `name` FROM $table WHERE year='$year' AND week_num='$week' AND practice='$practice' AND archived!='yes' ORDER BY region,fn,ln";
// Outstanding rows with all data
$SQL = "SELECT * FROM (SELECT DISTINCT *, CONCAT(fn,' ',ln) AS `name` FROM $table WHERE year='$year' AND practice='$practice' AND archived!='yes') AS `subquery` WHERE `name` NOT IN (SELECT DISTINCT CONCAT(fn,' ',ln) AS `name` FROM $table WHERE year='$year' AND week_num='$week' AND practice='$practice' AND archived!='yes') ORDER BY region,fn,ln";
This way you won't need to sort and process data at PHP-level. Can't test this since I don't have the database environment but it should work, may require some small changes.
Related
can someone help me on the proper way of using a variable with multiple values in MySQL LIKE clause?
by the way, I have two tables teacher and student.
Teacher table contains. (fname,lname,subject,yr,sec) columns and for the student table (lrn,yr,sec)
what I'm trying to achieve is to count the total number of students of the teacher from all sections.
Here's my query for getting teacher's sections:
<?php
$result= mysqli_query($con, "select *from teacher where lname
= 'Uy' and subject = 'Science & Technology 7'" );
while($rowx = mysqli_fetch_array($result)) {
$section = $rowx['sec'];
}
?>
echoing $section output this: Our Lady of FatimaOur Lady of Guadalupe
Heres my query to count the students.
<?php
$ratequery = mysqli_query($con, "SELECT *,
(SELECT COUNT(*) FROM student WHERE
sec LIKE '%$section%') AS responseCount FROM student");
$rateresult = mysqli_fetch_array($ratequery);
?>
Output: the count works but only the first value [Our Lady of Fatima] of $section is getting recognized by LIKE clause, so only 1 section is getting counted.
by the way, sorry for my bad English and explanation.
Use Section as a input for second query:
<?php
$final_result = array();
$result= mysqli_query($con, "select *from teacher where lname
= 'Uy' and subject = 'Science & Technology 7'" );
while($rowx = mysqli_fetch_array($result))
{
$section = $rowx['sec'];
$ratequery = mysqli_query($con, "SELECT *, (SELECT COUNT(*) FROM student WHERE
sec =$section) AS responseCount FROM student");
$rateresult = mysqli_fetch_array($ratequery);
array_push($final_result,array("section"=>$section,"rateresult"=>$rateresult));
}
var_dump($final_result); // Display section wise data
?>
somehow I have managed to achieve my goal it but in other way . I used WHERE IN clause instead of LIKE clause. stored my query results into an array.. then used implode to add seperator.
Thanks for the help mr. #ashnu
<?php
$query="$con, select *from teacher where lname = 'Uy' and subject = 'Science & Technology 7'";
$result = mysqli_query($query) or die;
$sections = array();
while($row = mysqli_fetch_assoc($result))
{
$sections[] = $row['sec'];
}
$string = implode("','",$sections)
?>
<?php
$ratequery = mysqli_query($con, "SELECT *,
(SELECT COUNT(*) FROM student WHERE sec IN ('$string')) AS responseCount FROM student");
$rateresult = mysqli_fetch_array($ratequery);
?>
I am creating a website in php to log ping pong scores for my school, and currently the player who wins will log the WinnerID, LoserID, PointsFor, PointsAgainst. I have two tables with the following relationships.
Table: users
user_ID (PK)
username
Elo
Table: games
game_id (PK)
WinnerID (FK)
LoserID (FK)
PointsFor
PointsAgainst
My insert statement in the php file is:
INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')"
Here is what I have tried, but it doesn't display the scores correctly.
SELECT min(u.username) 'Username', COUNT(g.WinnerID) 'Wins', sum(g.PointsFor) 'Points For', sum(g.PointsAgainst) 'Points Against', u.Elo 'Ranking'
from games g
LEFT JOIN users u
on g.WinnerID = u.user_id
Group by g.WinnerID
As you can see by the image above, the points for and points against totals don't add up. Currently, it only displays the stats for whoever was winner. Meaning if PlayerA wins 21-5, it will show up from the select statement, but PlayerB will not show a score of 5-21. Any help is appreciated.
PHP code for page to enter scores:
if(isset($_POST['btn-post']))
{
$opponent = $_POST["opponent"];
//$opponent = array_key_exists('opponent', $_POST) ? $_POST['opponent'] : false;
$userscore = mysql_real_escape_string($_POST['userscore']);
$oppscore = mysql_real_escape_string($_POST['oppscore']);
if($userscore != $oppscore)
{
if($userscore > $oppscore)
{
$Winner_ID = $_SESSION['user'];
$query = mysql_query("SELECT user_id FROM users WHERE username = '".$opponent."'");
$result = mysql_fetch_array($query) or die(mysql_error());
$Loser_ID = $result['user_id'];
$query1 = mysql_query("SELECT Elo FROM users WHERE user_id=".$_SESSION['user']);
$result1 = mysql_fetch_array($query1) or die(mysql_error());
$winnerRating = $result1['Elo'];
$query2 = mysql_query("SELECT Elo FROM users WHERE user_id=".$Loser_ID);
$result2 = mysql_fetch_array($query2) or die(mysql_error());
$loserRating = $result1['Elo'];
$rating = new Rating($winnerRating, $loserRating, 1, 0);
$results = $rating->getNewRatings();
if(mysql_query("UPDATE users SET Elo = " . $results['a'] . " WHERE user_id=".$_SESSION['user']))
{
}
else
{
?>
<script>alert('There was an error while entering winners(user) ranking...');</script>
<?php
}
if(mysql_query("UPDATE users SET Elo = " . $results['b'] . " WHERE user_id=".$Loser_ID))
{
}
else
{
?>
<script>alert('There was an error while entering losers(opp) ranking..');</script>
<?php
}
}
elseif($oppscore > $userscore)
{
$Loser_ID = $_SESSION['user'];
$query = mysql_query("SELECT user_id FROM users WHERE username = '".$opponent."'");
$result = mysql_fetch_array($query) or die(mysql_error());
$Winner_ID = $result['user_id'];
//get rating from user table in database
$query1 = mysql_query("SELECT Elo FROM users WHERE user_id=".$_SESSION['user']);
$result1 = mysql_fetch_array($query1) or die(mysql_error());
$loserRating = $result1['Elo'];
$query2 = mysql_query("SELECT Elo FROM users WHERE user_id=".$Loser_ID);
$result2 = mysql_fetch_array($query2) or die(mysql_error());
$winnerRating = $result1['Elo'];
$rating = new Rating($winnerRating, $loserRating, 1, 0);
$results = $rating->getNewRatings();
$results = $rating->getNewRatings();
if(mysql_query("UPDATE users SET Elo = " . $results['b'] . " WHERE user_id=".$_SESSION['user']))
{
}
else
{
?>
<script>alert('There was an error while entering losers(user) ranking...');</script>
<?php
}
if(mysql_query("UPDATE users SET Elo = " . $results['a'] . " WHERE user_id=".$Winner_ID))
{
}
else
{
?>
<script>alert('There was an error while entering winners(opp) ranking...');</script>
<?php
}
}
if(mysql_query("INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')"))
{
?>
<script>alert('Your scores were successfully entered');</script>
<?php
}
else
{
?>
<script>alert('There was an error while entering your score...');</script>
<?php
}
}
else
{
?>
<script>alert('There cannot be a tie in ping pong, please re-enter your scores...');</script>
<?php
}
}
?>
Your query fails because it doesn't take into account the rows where the player loses. You can fix that by using unions. The following query should do what you want:
SELECT username AS "Username",
SUM(wins) AS "Wins",
SUM(PF) AS "Points For",
SUM(PA) AS "Points Against",
elo AS "Ranking"
FROM (
(SELECT users.user_ID,
users.username AS username,
COUNT(games.WinnerID) AS wins,
SUM(games.PointsFor) AS PF,
SUM(games.PointsAgainst) AS PA,
users.Elo AS elo
FROM users, games
WHERE games.WinnerID = users.user_ID
GROUP BY users.user_ID)
UNION ALL
(SELECT users.user_ID,
users.username AS username,
0 AS wins,
SUM(games.PointsAgainst) AS PF,
SUM(games.PointsFor) AS PA,
users.Elo AS elo
FROM users, games
WHERE games.LoserID = users.user_ID
GROUP BY users.user_ID)
) AS t
GROUP BY username
ORDER BY user_ID;
Note that in the "losing query" the field PointsAgainst should be counter as the player's "points for" and vice-versa.
Try it as an inner join, and get rid of the MIN() on the username column:
SELECT u.username, COUNT(g.WinnerID),
SUM(g.PointsFor), SUM(g.PointsAgainst), u.Elo
FROM users u, games g
WHERE u.user_id = g.WinnerID
GROUP BY u.username, u.Elo;
Also, before anyone else takes you to task, you should be using mysqli instead of mysql (or better yet, PDO) and you should be using prepared statements instead of dynamic SQL.
Your
INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')
query contains the $userscore and $oppscore values in a potentially wrong order. The $Winner_ID and $Loser_ID may change in your conditional processing, but $userscore and $oppscore are not similarly flipped at that time.
Also your conditional structure is in general unnecessarily verbose. It seems like you should be able to just determine the winner and loser ID and score first, and then do all your processing once instead of resorting to error-prone copy-paste duplication of near-identical code.
I have an SQL query that looks like:
SET #fromyear = 1980;
SET #toyear = 1989;
SET #rank = 0;
SELECT test.Rank, test.Artist, test.Nominations
FROM(
SELECT
#rank:=#rank+1 as Rank,
noms.Artist,
noms.Nominations
FROM
(
SELECT COUNT(Name) as Nominations, Name as Artist
FROM Nominated
WHERE Year BETWEEN #fromyear AND #toyear
GROUP BY Name
ORDER BY Nominations DESC
) as noms
) as test
WHERE Rank BETWEEN 1 AND 5
it returns something like:
Rank Artist Nominations
1 Michael Jackson 6
2 Lionel Richie 6
// through 5
the SQL query works fine on phpMyAdmin. I'm trying to convert this for use with a PHP form. I've gotten this close:
<?php
$YEAR1POST=$_POST['YEAR1']; // user enters YEAR1 and YEAR2
$YEAR2POST=$_POST['YEAR2'];
$Rank = 0;
$ONE = 1;
$sql = "
SELECT test.Rank, test.Artist, test.Nominations
FROM(
SELECT
\"$Rank\" = ( \"$Rank\" + \"$ONE\" ) AS Rank,
noms.Artist,
noms.Nominations
FROM
(
SELECT COUNT(Name) as Nominations, Name as Artist
FROM Nominated
WHERE Year BETWEEN \"$YEAR1POST\" AND \"$YEAR2POST\"
GROUP BY Name
ORDER BY Nominations DESC
) as noms
) as test
WHERE Rank = 1
";
$result = mysql_query($sql, $connect);
while($row = mysql_fetch_assoc($result))
{
$rank = $row['Rank'];
$artist = $row['Artist'];
$nominations = $row['Nominations'];
echo "[Rank:] ". $rank;
echo "<br> [Artist:] ". $artist;
echo "<br> [Nominations:] ". $nominations;
echo "<br>";
echo "<br>";
}
?>
I'm not getting any data when i fetch the result. I'm pretty sure the issue is in:
SELECT
\"$Rank\" = ( \"$Rank\" + \"$ONE\" ) AS Rank,
I'm just not sure how to convert:
SELECT
#rank:=#rank+1 as Rank,
for use with a PHP form. Thanks
SQL is not procedural. Your SQL script is introducing a procedural element with rank, but PHP already is a procedural language.
If you extract just the base query:
$sql =
"SELECT COUNT(Name) as Nominations, Name as Artist
FROM Nominated
WHERE Year BETWEEN '$YEAR1POST' AND '$YEAR2POST'
GROUP BY Name
ORDER BY Nominations DESC";
Then you should be returning the same result set, minus the rank. You can generate the rank in the same way as the SQL client script, by using a PHP variable.
$rank = 1;
while($row = mysql_fetch_assoc($result)) {
$artist = $row['Artist'];
$nominations = $row['Nominations'];
echo "[Rank:] ". $rank;
echo "<br> [Artist:] ". $artist;
echo "<br> [Nominations:] ". $nominations;
echo "<br>";
echo "<br>";
$rank++;
}
While perfunctory at this juncture, you really should be using mysqli or PDO now -- the mysql_ api is soon to be removed entirely from PHP. Those are also much safer in terms of SQL injections and the elimination of the need for string escaping, so long as you use bind variables.
I have a MySQL database containing a user's country and whether they are an individual or an organisation. The field names are 'country' and 'type'.
Using PHP, I'd like to 'count' the number of countries, the number of individuals and the number of organisations in the database and then display the numbers in the following example format:
<p>So far, <strong>500</strong> individuals and <strong>210</strong> organisations from <strong>40</strong> countries have registered their support.</p>
I am currently listing the total number of records using the below code if this helps:
<?php
$link = mysql_connect("localhost", "username", "password");
mysql_select_db("database_name", $link);
$result = mysql_query("SELECT * FROM table_name", $link);
$num_rows = mysql_num_rows($result);
echo " $num_rows\n ";
?>
My PHP / MySQL skills are very limited so I'm really struggling with this one.
Many thanks in advance!
Ben
To get the number of countries:
SELECT COUNT(DISTINCT country) AS NumCountries FROM tableName
To get the number of individuals, or the number of organisations:
SELECT COUNT(*) AS NumIndividuals FROM tableName WHERE type = 'individual'
SELECT COUNT(*) AS NumOrganisations FROM tableName WHERE type = 'organisation'
What you are looking for is a count based on a grouping. Try something like this:
$sql = "SELECT type, count(*) as cnt FROM users GROUP BY type";
$result = mysql_query($sql);
$counts = array();
while ($row = mysql_fetch_assoc($result)) {
$counts[$row['type']] = $row['cnt'];
}
This will give you an array like
Array (
'individual' => 500,
'organization' => 210
)
For counting the countries, use the first statement as posted by Hammerite.
EDIT: added a verbose example for counting the countries
$sql = "SELECT COUNT(DISTINCT country) AS NumCountries FROM users";
$result = mysql_query($sql);
$number_of_countries = 0;
if ($row = mysql_fetch_assoc($result)) {
$number_of_countries = $row['NumCountries'];
}
This altogether you can then print out:
printf('<p>So far, <strong>%d</strong> individuals and <strong>%d</strong> '.
'organisations from <strong>%d</strong> countries have registered '.
'their support.</p>', $counts['individual'], $counts['organization'],
$number_of_countries);
The answer is to retrieve the answer by using the COUNT(*) function in SQL:
SELECT COUNT(*) AS individual_count FROM user WHERE type = 'individual';
SELECT COUNT(*) AS organization_count FROM user WHERE type = 'organization';
SELECT COUNT(*) AS country_count FROM user GROUP BY country;
The last will group your query set by the country name, and will result in one row for each country. Using COUNT on this result set will give the count of distinct coutries.
You can then fetch this value by using mysql_fetch_assoc on your $result from mysql_query, and the answer will be contained in 'invididual_count', 'organization_count' and 'country_count' for each query.
Thank you for all of your help with this (especially Cassy).
I think it's worthwhile displaying the full code in case anybody else comes across a similar requirement in the future:
<?php
$link = mysql_connect("localhost", "username", "password");
mysql_select_db("database_name", $link);
$sql = "SELECT type, COUNT(*) as cnt FROM table_name GROUP BY type";
$result = mysql_query($sql);
$counts = array();
while ($row = mysql_fetch_assoc($result)) {
$counts[$row['type']] = $row['cnt'];
}
$sql = "SELECT COUNT(DISTINCT country) AS NumCountries FROM table_name";
$result = mysql_query($sql);
$number_of_countries = 0;
if ($row = mysql_fetch_assoc($result)) {
$number_of_countries = $row['NumCountries'];
}
printf('<p><strong>So far, <em class="count">%d</em> individuals and <em class="count">%d</em> organisations from <em class="count">%d</em> countries have registered their support.', $counts['Individual'], $counts['Organisation'], $number_of_countries); ?>
If you're just looking for the number of rows returned try this:
$result = mysql_db_query($db, $query);
$num_rows = mysql_num_rows($result);
Another option would be to execute a separate query with the mysql count function and use the result from that.
So I have a list of CSVs in one table. (EG: 1,3,19 )
I want to search out all of the usernames from the other table where the ids match any of those.
I feel like I should be able to do something like:
<?
$query = "SELECT player_ids FROM cast_list WHERE game='".$gameid."' ";
$result = mysql_query($query) or die(mysql_error());
$playerquery = "SELECT username,id FROM players WHERE id IN (".$result.") ORDER BY username;
$player_result = mysql_query($playerquery) or die(mysql_error());
echo "<ul>";
while ($row = mysql_fetch_array($player_result) ) {
echo "<li>".$row['username']."</li>";
}
echo "</ul>";
?>
but I can't get it to work. What am I doing wrong?
You can also use a subquery (which will be faster):
$playerquery = "SELECT username,id
FROM players
WHERE id IN (SELECT player_ids FROM cast_list WHERE game='".$gameid."')
ORDER BY username";
Btw if game is an integer field you don't have put quotes (' ') around the value.
The idea is correct, but you need to transfer the $result to an actual string array:
$game_ids = array();
while ($row = mysql_fetch_array($result) ) {
$game_ids[] = .$row[1];
}
Now using implode to convert the array to a comma separated values with a comma:
$playerquery = "SELECT username,id FROM players WHERE id IN (" . implode(",",$result) . ") ORDER BY username;