I have a script designed to print out values of students who have accrued more than 3 tardies. I want this script to print out both the student name, and the amount of times they've been tardy, but so far I've been only able to print out their names with the following script:
$sql = "select DISTINCT StudentID,classid,date from attendance_main where status = 'Tardy' AND classid like '%ADV%'";
$result = mysql_query($sql) or die (mysql_error());
while($row=mysql_fetch_array($result)) {
$studentid = $row['StudentID'];
$sql2 = "select distinct StudentID,classid,date from attendance_main where StudentID = '$studentid' AND status = 'Tardy' AND classid like '%ADV%'";
$result2 = mysql_query($sql2) or die (mysql_error());
while($row2=mysql_fetch_array($result2)) {
$tardycount = mysql_num_rows($result2);
$studentid = $row2['StudentID'];
if($tardycount >= 3) {
$sql3 = "select * from students where rfid = '$studentid'";
$result3 = mysql_query($sql3) or die (mysql_error());
while($row3=mysql_fetch_array($result3)) {
$fname[] = $row3['fname'];
}
}
}
}
$newdata = array_unique($fname);
foreach ($newdata as $value) {
echo $value;
}
I can't think of how to intuitively do this. Keeping it all in the while loop didn't work (I had multiple results coming up for the same students despite requesting unique entries) so using array_unique was the only method I could think of.
Thanks for any help!
Something like this:
SELECT
attendance_main.StudentID,
students.fname,
COUNT(attendance_main.*) AS `times_tardy`
FROM
attendance_main
INNER JOIN
students
ON
attendance_main.StudentID = students.rfid
WHERE
attendance_main.status = 'Tardy'
AND
attendance_main.classid like '%ADV%'
GROUP BY
attendance_main.StudentID
HAVING
`times_tardy` > 3
Joining the two tables gets you the tardy count and student's name in one query, and the GROUP BY and HAVING clause that get you only the students with more than 3 tardy entries.
You can (and should) do almost everything in SQL. It should look something like this.
select StudentID, classid, date count(*)
from attendance_main
where status = 'Tardy' AND classid like '%ADV%'"
left join student on student.rfid = attendance_main.StudentId
group by StudentId
having count(*) > 3;
Here's how it works.
select the results you want to work with:
select StudentID, classid, date count(*)
from attendance_main
where status = 'Tardy' AND classid like '%ADV%'"
Join the students to your result set on the common id
left join student on student.rfid = attendance_main.StudentId
group everything by student. We use count(*) to get the number of items. We know we're only dealing with tardies because of the where clause in the select.
group by StudentId
limit the results to only tardies above 3 with the having claues (this is like a where clause for the group by)
having count(*) > 3;
Related
May I know if I can combine queries from different variable or is there any other way. I want to insert $query_1 to $query_2
Example:
$sql = "SELECT l_id from mlk";
$result = mysqli_query($conn, $sql);
$count = mysqli_num_rows($result);
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
$l_id[] = $row["l_id"];
}
}
mysqli_free_result($result);
foreach($l_id as $row){
$query_1= "(select count(*) from staff s where s.l_id = $row) as mlk_$row,";
}
$query_2= "SELECT mlk.lokasi,
//insert $query_1 here
from mlk INNER JOIN staff WHERE staff.l_id=mlk.l_id GROUP BY mlk.lokasi";
$result = mysqli_query($conn, $sql);
mlk is a table that stores staff working location
$query_2 will display the Location Name and I also want to display the total number of staff on that particular location. eg, Kuala Lumpur, 10
Just include the counting in the 2nd query:
SELECT mlk.lokasi, count(*) as no_of_staff
from mlk
INNER JOIN staff on staff.l_id=mlk.l_id
GROUP BY mlk.lokasi
I also changed the implicit join into an explicit one by moving the join condition from the where clause to the on clause.
Use left join for this to show all the locations and then each location staff count.
SELECT mlk.lokasi, count(*) as no_of_staff
from mlk
LEFT JOIN staff on staff.l_id=mlk.l_id
GROUP BY mlk.lokasi order by mlk.lokasi ASC
Basically, I am seeking to know if there is a better way to accomplish this specific task.
Basically, what happens is I query the db for a list of "project needs" -- These are each uniquer and only appear once.
Then, I search another table to find out how many members have the required "skills - which are directly correlated to the project needs".
I accomplished exactly what I was trying to do by running a second query and then inserting them into an array like this:
function countEachSkill(){
$return = array();
$query = "SELECT DISTINCT SKILL_ID, SKILL_NAME FROM PROJECT_NEEDS";
$result = mysql_query($query) or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)){
$query = "SELECT COUNT(*) as COUNT FROM MEMBER_SKILLS WHERE SKILL_ID = '".$row['NEED_ID']."'";
$cResult = mysql_query($query);
$cRow = mysql_fetch_assoc($cResult);
$return[$row['SKILL_ID']]['Count'] = $cRow['COUNT'];
$return[$row['SKILL_ID']]['Name'] = $row['SKILL_NAME'];
}
arsort($return);
return $return;
}
But I feel like there has to be a better way (perhaps using some kind of join?) that would return this in a result set to avoid using the array.
Thanks in advance.
PS. I know mysql_ is depreciated. It is not my choice on which to use.
SELECT P.SKILL_ID, P.SKILL_NAME, COUNT(M.SKILL_ID) as COUNT FROM PROJECT_NEEDS P INNER JOIN MEMBER_SKILLS M
ON P.SKILL_ID=M.SKILL_ID
GROUP BY P.SKILL_ID, P.SKILL_NAME
I've adjusted Nriddens answer to accomodate for the select distinct, Im under the belief that his adjustment would be ok given SKILL_ID is a primary key
function countEachSkill(){
$return = array();
$query = "
SELECT
COUNT(*) AS COUNT,
PROJECT_NEEDS.SKILL_NAME,
PROJECT_NEEDS.SKILL_ID
FROM
(SELECT DISTINCT
SKILL_ID, SKILL_NAME
FROM
PROJECT_NEEDS) AS PROJECT_NEEDS
INNER JOIN
MEMBER_SKILLS
ON
MEMBER_SKILLS.SKILL_ID = PROJECT_NEEDS.SKILL_ID
GROUP BY PROJECT_NEEDS.SKILL_ID";
$result = mysql_query($query) or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)){
$return[$row['SKILL_ID']]['Count'] = $row['COUNT'];
$return[$row['SKILL_ID']]['Name'] = $row['SKILL_NAME'];
}
arsort($return);
return $return;
I am subquerying on the select distinct because I dont believe you have a dedicated skills table with an auto inc primary key, if that was there I wouldn't be using a subquery.
Can you test this query
select project_needs.*,count(members_skills.*) as count from project_needs
inner join members_skills
on members_skills.skill_id=project_needs.skill_id Group by project_needs.skill_name, project_needs.skill_id
I have an array
$genreQuery = $con ->query ("select distinct(movie_year) from movies");
$movieGenre = array();
$movieTitle = array();
$movieList = array();
while($row = $genreQuery->fetch_object()) {
$movieGenre[] = $row;
}
foreach($movieGenre as $MGenre){
$query = $con ->query
("
select '$MGenre->movie_year' movie_year, IFNULL(count(*)/(select count(*)
from user_movie_ratings where user_id = '$userid'),0) rating
from user_movie_ratings umr,
movies m
where umr.user_id = '$userid'
and umr.movie_id = m.id
and m.movie_year = '$MGenre->movie_year' ORDER BY rating DESC;
");
while($row = $query->fetch_object()) {
$movieTitle[] = $row;
}
}
$text = "";
foreach($movieTitle as $MTitle){
if (empty($text)){
$text = "\"".$MTitle->movie_year."\"";}
else{
$text = $text.",\"".$MTitle->movie_year."\"";
}
}
$list = $con ->query
("
SELECT movie_name, avg_rating, image, id, genre
FROM movies
WHERE id NOT IN (SELECT movie_id FROM user_movie_ratings WHERE user_id = '$userid')
ORDER BY field(movie_year, $text), avg_rating DESC;
");
while($row = $list->fetch_object()) {
$movieList[] = $row;
}
The array is filled by the above query, what I want to do is sort it by the rating so that is looks like this
year rating
2014 0.0001
2015 0.0000
2013 0.0000
1967 0.0000
.... ......
.... ......
etc etc
I have tried adding ORDER BY rating DESC to the query, but that does not work and when I use rsort($movieTitle) it sorts by the year not the rating do I need to do some kind of multidimensional sort, or is there another way?
I would guess that ordering by rating does not work as you seem to be running multiple queries in a foreach loop and each iteration gets one year. So in that case, your order would be by year and then in the year by rating.
You should get rid of that loop and only do one query and then the condition and sort order would be:
...
AND m.movie_year IN (the,years,you,want)
ORDER BY rating DESC
By looping over the $movieGenre like you do now, you can easily generate a comma separated list for the years to use in the IN statement.
Edit: Based on your comment you want all years, so the foreach loop and the year condition in the query are unnecessary.
You probably want something like:
SELECT m.movie_year, IFNULL(count(*)/(select count(*)
from user_movie_ratings where user_id = '$userid'),0) rating
FROM user_movie_ratings umr,
movies m
WHERE umr.user_id = '$userid'
AND umr.movie_id = m.id
ORDER BY rating DESC
Assuming of course that the user ID is safe to use in a query, you should really use a prepared statement to avoid potential sql injection.
Now you have all your results in one query so there is no need for the outer loop any more.
I have to tables.
The first one (members) contains my customers
id|name|email|key
The second (types) contains listings customer subscribes to
id|customer_id|type|active
What I would like to do is to list all members that subscribed to a type of list.
I can do this with 2 sql:s, but I guess there must be a better and faster way using som kind if JOIN maby and besides I get the wrong ORDER for my customers doing my way. I want ORDER by name.
<?
$type ='555';
$sql = mysql_query(" SELECT * FROM types WHERE type='$type' && active='1' ");
while($a = mysql_fetch_array($sql))
{
$sql2 = mysql_query(" SELECT * FROM members WHERE id='{$a['customer_id']}' ");
while($b = mysql_fetch_array($sql2))
{
echo 'Name: '.$b['name'].'<br>';
}
}
?>
mysql_query(" SELECT * FROM types INNER JOIN members ON types.customer_id = members.id WHERE type='$type' AND active='1' ORDER by members.name ASC");
This should do the trick for you
SELECT * FROM members
JOIN types ON members.id = types.customer_id
WHERE types.type = ? AND types.active = '1'
ORDER BY members.name
perhaps this:
SELECT m.name, m.email
FROM members m left join types t
ON m.id=t.customer_id
WHERE t.type='$type' and t.active='1';
I have this query which gives me the transactions for a user, and the output is a table with the information. There is this row named basket_value which contains some numbers, and I need to get the sum of those numbers. Could you please help me?
$query3 = 'SELECT users.first_name,users.last_name,users.phone,
retailer.date, SUM(retailer.basket_value),
retailer.time,retailer.location,retailer.type_of_payment
FROM users ,retailer
WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id GROUP BY users.user_id';
$result3 = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result3)) {
echo "Total ". $row['user_id']. " = $". $row['SUM(basket_value)'];
echo "<br />";
}
I suppose that also your query have some problem and suppose that you have an id to retrieve users, I would do in that way
$query3 = 'SELECT users.user_id,users.first_name,users.last_name,
users.phone, retailer.date,
SUM(retailer.basket_value) as total_sum,
retailer.time,retailer.location,retailer.type_of_payment
FROM users ,retailer WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id
GROUP BY users.user_id,users.first_name,users.last_name,
users.phone, retailer.date,retailer.time,retailer.location,
retailer.type_of_payment '
$result = $mysqli->query($query3);
Now if you want the sum for each user:
while ($row = $result->fetch_row()) {
echo "Player: ".$row['user_id']." total: ".$row['total_sum'];
}
If you want the WHOLE GLOBAL sum, you have to way:
Modify your query in that way:
SELECT SUM(retailer.basket_value) as total_sum
FROM retailer
Sum into while loop like: $total += $row['total_sum'];
You're missing a GROUP BY on your query. You most likely want to add GROUP BY users.user_id
Try this query:
SELECT u.first_name, u.last_name, u.phone, SUM(r.basket_value) as total_sum
FROM users u
JOIN retailers r
ON u.user_id = r.user_id
WHERE u.user_id="'.$id_user.'"
GROUP BY u.user_id
You can omit all other columns in the select list and only have the sum() aggregate run on the set to avoid the GROUP BY clause.
$query3 = 'SELECT SUM(retailer.basket_value) as total_sum
FROM users ,retailer WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id';