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.
Related
I want to iterate the values of the array $code and $per_sectionfrom the query below. What looping method should i use? Or is this the right thing to do?
//total students
$count_query=mysql_query("select total_students from subject where teacherid = '$get_id'");
while($count_row=mysql_fetch_array($count_query)){
$total += $count_row['total_students'];
}
$query = mysql_query( "Select code,total_students from subject where teacherid='$get_id'");
while($result=mysql_fetch_assoc($query))){
$section = ($result['total_students']/ $total)*30;
$per_section[] = round($section, 0, PHP_ROUND_HALF_UP);
$code[] = $result['code'];
}
//perform this statement for a number of times depending on the number of array of $code..
$user_query=mysql_query("select * from result where subject_id ='$code' and faculty_id = '$get_id'LIMIT $per_section ")or die(mysql_error());
while($row=mysql_fetch_assoc($user_query)){
...
}
Sample data:
Subject table
code total_students teacherid
IT230 45 11-0009
IT213 44 11-0009
IT214 40 11-0009
result table
subject__id faculty_id
IT230 11-0009
IT213 11-0009
IT214 11-0009
Expected Results:
I want to show only 30 records of students that matches the result table.
Since the total students of that teacher are 45, 44, 40 = 129. This is the $per_section
IT230 only needed students = (45/129)*30 = 10.46 or i need only 11 of the results.
IT213 only needed students = (44/129)*30 = 10.23 or i need only 10 of the results.
IT214 only needed students = (40/129)*30 = 9.3 or i need only 9 of the results.
I want to search for the records in IT230 and select only 11 of them.
IT213 for only 10 and IT214 for 9. Since i only have 3 records, only these three records will show up.
As mentioned in the comments on your question, it is much better practice to use prepared statements via PDO and JOIN the two tables:
$dbh = new PDO('mysql:host=localhost;dbname=mydb', 'username', 'password');
$stmt = $dbh->prepare('
SELECT result.*
FROM result
JOIN student ON result.subject_id = student.code
WHERE student.id = :id
');
$stmt->execute(['id' => $id]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
Use one query that joins the two tables:
SELECT s.total_students, s.code, r.*
FROM students AS s
LEFT JOIN result AS r ON r.subject_id = s.code
WHERE s.teacher_id = '$get_id' AND r.faculty_id = '$get_id'
ORDER BY s.code
Then you can get all the information in a single loop:
while ($result = mysqli_fetch_assoc($query)) {
if (!isset($per_section[$result['code']]) {
$per_section[$result['code']] = round($result['total_student']/$total*30, 0, PHP_ROUND_HALF_UP);
$code[] = $result['code'];
}
if ($result['subject_id'] !== null) {
// do stuff with columns from result table here
}
}
I'm trying to show stuff queried from two tables, but on one html table. Data is shown for the last 30 days, based on which, an html table is being generated.
Currently I'm stuck using two queries and generating two html tables:
$query1 = mysqli_query( $con, "SELECT date, stuff* " );
while( $record = mysqli_fetch_array( $query1 ) ){
echo '<html table generated based on query>';
}
$query2 = mysqli_query( $con, "SELECT date, other stuff*" );
while( $record = mysqli_fetch_array( $query2 ) ){
echo '<another html table generated based on query2>';
}
Is there a possibility to show both queries on one html table instead?
Note that it gets tricky since we have dates on one table which are not necessarily found in the second table or vice-versa.
Thanks for the support guys. So far I'm stuck at this:
SELECT * FROM user_visit_logs
LEFT JOIN surfer_stats ON user_visit_logs.date = surfer_stats.date
UNION
SELECT * FROM user_visit_logs
RIGHT JOIN surfer_stats ON user_visit_logs.date = surfer_stats.date
The query completes, but the 2nd table fields are all null:
Furthermore, it breaks when I add additional clause like:
WHERE user_id = '{$_SESSION['user_id']}' ORDER BY date DESC LIMIT 30
I think you are after FULL OUTER JOIN concept:
The FULL OUTER JOIN keyword returns all rows from the left table (table1) and from the right table (table2)
In which you may use common dates as a shared row.
So the query will get to simple one:
$query = "
SELECT table1.date, stuff
FROM table1
LEFT OUTER JOIN table2 ON table1.date = table2.date
UNION
SELECT table2.date, other_stuff
FROM table1
RIGHT OUTER JOIN table2
ON table1.date = table2.date
";
$result = mysqli_query( $con, $query );
while( $record = mysqli_fetch_array( $result ) ){
echo '<html table generated based on query>';
}
Example
This is an schematic diagram of FULL OUTER JOIN concept:
After running into quite a few bumps with this one, I finally managed to merge 2 columns from each table and also to use where and sort clauses on them with the following query:
( SELECT user_visit_logs.user_id,user_visit_logs.date,unique_hits,non_unique_hits,earned,sites_surfed,earnings FROM user_visit_logs
LEFT OUTER JOIN surfer_stats ON user_visit_logs.user_id = surfer_stats.user_id AND user_visit_logs.date = surfer_stats.date where user_visit_logs.user_id = 23 ORDER BY date DESC LIMIT 30 )
UNION
( SELECT surfer_stats.user_id,surfer_stats.date,unique_hits,non_unique_hits,earned,sites_surfed,earnings FROM user_visit_logs
RIGHT OUTER JOIN surfer_stats ON user_visit_logs.user_id = surfer_stats.user_id AND user_visit_logs.date = surfer_stats.date where user_visit_logs.user_id = 23 LIMIT 30 )
Simplified, "user_visit_logs" and "surfer_stats" were the 2 tables needed to be joined.
Absolutely. Just pop them both into a variable:
$data = '';
$query = mysqli_query($con,"SELECT date, stuff* ");
while($record = mysqli_fetch_array($query)) {
$data.= '<tr><td>--Your Row Data Here--</td></tr>';
}
$query2 = mysqli_query($con,"SELECT date, other stuff*");
while($record = mysqli_fetch_array($query2)) {
$data .= '<tr><td>--Your Row Data Here--</td></tr>';
}
echo "<table>$data</table>";
Instead of using echo in your loop, you're just storing the results in $data. Then, you're echoing it out after all data has been added to it.
As for your second point, it's not a big deal if fields don't exist. If they're null, you'll just have a column that doesn't have data in it.
Here's an example with fake column names:
$data = '';
$query = mysqli_query($con,"SELECT date, stuff* ");
while($record = mysqli_fetch_array($query)) {
$data.= "<tr><td>{$record[id]}</td><td>{$record[first_name]}</td><td>{$record[last_name]}</td></tr>";
}
$query2 = mysqli_query($con,"SELECT date, other stuff*");
while($record = mysqli_fetch_array($query2)) {
$data .= "<tr><td>{$record[id]}</td><td>{$record[first_name]}</td><td>{$record[last_name]}</td></tr>";
}
echo "<table><tr><th>ID</th><th>First Name</th><th>Last Name</th></tr>$data</table>";
I have a feeling I may have misunderstood the need. If so, I apologize. If you can elaborate just a bit more I can change my answer :)
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 thought this would be simple but I'm having a tough time figuring out why this won't populate the the data array.
This simple query works fine:
$queryPrice = "SELECT price FROM price_chart ORDER BY id ASC LIMIT 50";
$resultPrice = mysqli_query($conn, $queryPrice);
$data = array();
while ($row = mysqli_fetch_array($resultPrice)) {
$data[] = $row[0];
}
But instead I want it to choose the last 10 results in Ascending order. I found on other SO questions to use a subquery but every example I try gives no output and no error ??
Tried the below, DOESN'T WORK:
$queryPrice = "SELECT * FROM (SELECT price FROM price_chart ORDER BY id DESC LIMIT 10) ORDER BY id ASC";
$resultPrice = mysqli_query($conn, $queryPrice);
$data = array();
while ($row = mysqli_fetch_array($resultPrice)) {
$data[] = $row[0];
}
I also tried specifying the table name again and using the IN, also doesn't work:
$queryPrice = "SELECT price FROM price_chart IN (SELECT price FROM price_chart ORDER BY id DESC LIMIT 10) ORDER BY id";
$resultPrice = mysqli_query($conn, $queryPrice);
$data = array();
while ($row = mysqli_fetch_array($resultPrice)) {
$data[] = $row[0];
}
In both examples my array is blank instead of returning the last 10 results and there are no errors, so I must be doing the subquery wrong and it is returning 0 rows.
The subquery doesn't select the id column, so you can't order by it in the outer query. Also, MySQL requires that you assign an alias when you use a subquery in a FROM or JOIN clause.
$queryPrice = "SELECT *
FROM (SELECT id, price
FROM price_chart
ORDER BY id DESC LIMIT 10
) x ORDER BY id ASC";
$resultPrice = mysqli_query($conn, $queryPrice) or die (mysqli_error($conn));
$data = array();
while ($row = mysqli_fetch_assoc($resultPrice)) {
$data[] = $row['price'];
}
You would have been notified of these errors if you called mysqli_error() when the query fails.
Your second query is the closest. However you need a table alias. (You would have seen this if you were kicking out errors in your sql. Note you will need to add any field that you wish to order by in your subquery. In this case it is id.
Try this:
SELECT * FROM (SELECT price, id
FROM price_chart ORDER BY id DESC LIMIT 10) as prices
ORDER BY id ASC
You must have errors, because your SQL queries are in fact incorrect.
First, how to tell you have errors:
$resultPrice = mysqli_query (whatever);
if ( !$resultprice ) echo mysqli_error($conn);
Second: subqueries in MySQL need aliases. So you need this:
SELECT * FROM (
SELECT id, price
FROM price_chart
ORDER BY id DESC LIMIT 10
) AS a
ORDER BY id ASC";
See the ) AS a? That's the table alias.
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;