MySQL select row with and without relation - php

Let say I have 2 mysql tables 'movies' and 'seen'
If a user already saw a movie there is a record in the 'seen' table, with his userID and the movieID
I have to print ALL the movies, and then if the user already saw the movie print "already watched" otherwise "to watch".
At this time I use PHP with 2 seprate queries:
<?php
$res = mysql_query( "SELECT * FROM movies" );
while( $row = mysql_fetch_assoc( $res ) ) {
echo $row['movie_name'];
$res2 = mysql_query( "SELECT * FROM seen WHERE userID = '$uid' AND movieID = '$row[id]' LIMIT 1" );
if( mysql_num_rows( $res2 ) == 1 ) { echo "already watched"; } else { echo "to watch"; }
}
There is a way to do that with ONE single query?
With JOIN on "movies.id = seen.movieID" it only print the wahtched movies, with "WHERE movies.id NOT IN ( SELECT seen.movieID FROM seen WHERE seen.userID = '$uid' )" it only print the not watched..

In this cases you can use from LEFT JOIN, in the left join you can see data which is on table first and is not on second table.
SELECT * FROM movies LEFT JOIN seen ON movies.id = seen.movieID
if data of seen table was on result data exist if not user did not seen.
Also you can use UNION in your solution and merge to query

You can create a sub query which aggregates the number of times a user has seen a movie:
SELECT m.userid, m.movieid,
case when s.seencount is null then 0 else 1 end as seenmovie
FROM movies m left join
(SELECT movieid, userid, count (id)
FROM seen
GROUP BY movieid, userid) as s on m.movieid = s.movieid and m.userid = s.userid
This will also handle cases where users have watched a movie more than once
I'm on a mobile device so apologies if any typos but you should get the idea

SELECT * FROM `movies`
LEFT JOIN ( select movieName,'Watched' as w from seen where userId='$uid' ) s
on s.movieId=movies.movieId
Will give watched when movie is watched otherwise it will give NULL

Related

PHP MySql Query Get Sum Per User

I have users with rating and I want to show the total amount of rating of each user. I have 2 tables: users and feedback. I have 4 users in USERS table. And in table FEEDBACK (consists of applicant_id and app_experience columns) I have the rating of each user. But, I have several ratings for each person.
$sql4 = "
SELECT SUM(app_experience) as app_experience
, applicant_id
FROM feedback f
JOIN users u
ON u.id=f.applicant_id
GROUP
BY feedback.applicant_id
";
$res4 = mysqli_query($db,$sql4) or die(mysqli_error($db));
This is my output, but it prints only 2 users, because in table FEEDBACK 2 of the users do not have any feedback yet:
foreach ($res4 as $row)
{
echo "".$row['applicant_id']."----".$row['app_experience']."";
echo "<br>";
}
My question is how to output all 4 users and I want to show the total number of rating next to each user.
I am doing something like this, but I do not know where to add the foreach loop above in the code below. Do you have any ideas?:
$sql2 = "SELECT * FROM users";
$res2 = mysqli_query($db,$sql2) or die(mysqli_error($db));
while($row2 = mysqli_fetch_assoc($res2))
{
$id = $row2['id'];
$name = $row2['name'];
}
You just have to modify the below statement :
$sql4 = "SELECT SUM(app_experience) as app_experience, applicant_id FROM feedback INNER JOIN users ON users.id=feedback.applicant_id GROUP BY feedback.applicant_id";
to :
$sql4 = "SELECT COALESCE(SUM(app_experience), 0) as app_experience, applicant_id FROM users LEFT JOIN feedback ON users.id=feedback.applicant_id GROUP BY users.id";
The users LEFT JOIN feedback ... clause will allow the query to return a row even for users who do not have a feedback yet.
The COALESCE(SUM(app_experience), 0) will evaluate to 0 when a user has no feedback yet.
With this solution you don't need to loop.
SELECT users.*, (SELECT SUM(app_experience) FROM feedback WHERE applicant_id = users.id) as feedback FROM users
Selects all users and their feedback in a short SQL
As written, your query will not run. The GROUP BY clause is referencing feedback, but that reference has been changed to f by the alias.
You appear to want a LEFT JOIN:
SELECT u.id, SUM(f.app_experience) as app_experience
FROM feedback f LEFT JOIN
users u
ON u.id = f.applicant_id
GROUP BY u.id;
This will return a NULL value for app_experience. If you want a value (such as 0) use COALESCE(SUM(f.app_experience), 0).

PHP/MYSQL counting orders

Here is database table:
$sql[2] = "SELECT u.* , oi.* , COUNT(oi.user_id) AS count
FROM users u, order_items oi
WHERE u.id=oi.user_id ";
$result3= mysqli_query($conn,$sql[2]) or die(mysqli_error());
if (mysqli_num_rows($result3) > 0) {
while ($record = mysqli_fetch_array($result3)) {
echo $record['count'];
}
}
I want to count how much order have every user. Example: Like Thomas have 3 order, but my code is writing 4, i want to write Thomas (3), Gracian(1). Any idea how to fix it ?
Use this query:
SELECT u.id,
COUNT(oi.user_id) AS orderCount
FROM users u
LEFT JOIN order_items oi
ON u.id = oi.user_id
GROUP BY u.id
The reason we count user_id from the order_items table is because of the edge case where a given user has no orders. In this case, we want to make sure that his count would appear as zero. The COUNT function ignores NULLs, which is what we want.
There is another way to perform the sql query using subqueries:
SELECT id,
email,
address,
name,
(SELECT count(user_id) FROM order_items WHERE user_id = users.id) AS orderCount FROM users;

compare mysql id between 2 table and display all with match id echo yes

I want to compare mysql id between 2 table and display all name with match id echo yes.
I have 2 table one is wine and the other is user. I will use unique id column from table wine. But in table user, I will use wine_id column which are not unique.
This is mysql code that will get a matching id from table wine and user.
$sql="SELECT id FROM `winelist` w WHERE page = 'Chardonnay USA' and
EXISTS(
SELECT wine_id FROM `user_wine_history` u WHERE user_name = 'bon'
AND u.wine_id = w.id);";
$result= mysql_query($sql);
while($data= mysql_fetch_array($result)) {
}
and this is the code for for listing all the name in wine.
$sql2 ="SELECT id, name, year, grape, price, instock FROM winelist WHERE page ='Chardonnay USA';";
$result2 = mysql_query($sql2);
while($data2 = mysql_fetch_array($result2)) {
}
I tried to use this code in listing name while loop but it didn't work.
if($data2['id'] == $data['id']) {
echo "yes";
}
else
{
echo "fail";
}
Can anybody give me some advice how to solve this?
Thank you in advance.
You can use LEFT JOIN instead and do this within the query using the CASE expression, something like:
SELECT
w.id , w.page, w.name, w.year,
u.user_name, u.id user_id, u.wine_id uwine_id,
CASE
WHEN u.id IS NOT NULL THEN 'Yes'
ELSE 'No'
END AS IsMatching
FROM `winelist` w
LEFT JOIN `user_wine_history` u ON w.id = u.wine_id
AND w.page = 'Chardonnay USA'
AND u.user_name = 'bon';
This will select a new column IsMatching with values yes or no to indicate whether the wine id is found in the other table or not.
SQL Fiddle Demo
Use Join:
$id= Here the input
SELECT id FROM `winelist` w
INNER JOIN `user_wine_history` u
ON u.wine_id = w.id
WHERE w.page = 'Chardonnay USA' AND u.user_name = 'bon'
AND w.id = '".$id."'

join two tables order by date and display results

I'm trying to make a function kinda similar to facebook's notification window. Their function seems to combine any kind of event and display them after date.
So i have 2 tables :
Article and comments.
both have 2 similar rows : uniquepostowner and date_posted.
I want to join them up and display them one after another.
Example :
User A has posted a comment (04.05.2012 5:30)
User B Has posted a comment (04.05.2012 6:30)
User C has written an article (04.05.2012 7:30)
user D has posted a comment (04.05.2012 8:30)
However, i'm struggling with both joining these 2 and displaying the results.
Reading others with similar scenarios ive tried this as a query:
$sesid = $_SESSION['user_id'];
$sql = "SELECT X.* FROM ( SELECT * FROM `article` WHERE uniquepostowner = {$sesid} UNION SELECT * FROM `comments` WHERE uniquepostowner = {$sesid} ) X ORDER BY X.`date_posted`";
$result = mysql_query($sql);
Then trying to fetch the results like this:
while($row = mysql_fetch_array($result))
{
echo $row['article.id'];
}
Tables:
**article**:
id
title
content
uniqueuser
date_posted
full_name
uniquepostowner
**comments**:
id
pid (same as article.id)
date_posted
content
full_name
uniquepostowner
there are more rows to these tables, but they are irrelevant.
But no success. Any help is greatly appreciated as always! :)
Currently i'm trying this, but its not doing what i want.
$sql = "SELECT * FROM article a INNER JOIN comments c WHERE a.uniquepostowner = {$sesid} AND c.uniquepostowner = {$sesid}
ORDER BY a.date_posted DESC , c.date_posted DESC ";
I think this is what you need:
UPDATED:
$sesid = $_SESSION['user_id'];
$sql = "
SELECT
X . *
FROM
(SELECT
id,
date_posted,
content,
full_name,
uniquepostowner,
'article' AS type
FROM
article
WHERE
uniquepostowner = {$sesid} UNION SELECT
id,
date_posted,
content,
full_name,
uniquepostowner,
'comment' AS type
FROM
comments
WHERE
uniquepostowner = {$sesid}) X
ORDER BY X.date_posted
";
$result = mysql_query($sql);
And you can iterate with:
while($row = mysql_fetch_array($result))
{
if($row['type']=='article'){
echo "User " . $row['full_name'] . " has written an article (".$row['date_posted'].")<br>";
} else {
echo "User " . $row['full_name'] . " has posted a comment (".$row['date_posted'].")<br>";
}
}
You can check it out at:
http://sqlfiddle.com/#!2/38778/8
you should try to rephrase your sql to only use the columns both tables have in common:
SELECT uniquepostowner,date_posted FROM `article` WHERE uniquepostowner = {$sesid}
UNION
SELECT uniquepostowner,date_posted FROM `comments` WHERE uniquepostowner = {$sesid}
ORDER BY date_posted
there are some more examples in the mysql manual.
You must make the collumns on each query of the union equal:
SELECT X.* FROM ( SELECT **uniquepostowner** FROM `article` WHERE uniquepostowner = {$sesid} UNION SELECT **uniquepostowner** FROM `comments` WHERE uniquepostowner = {$sesid} ) X ORDER BY X.`date_posted`
This is just a example, in the union, both queries must return the same amount of fields, I sugest that you return only the filds that both tables have in commom.
Maybe I'm missing the point, but wouldn't this solve the problem:
SELECT articles.*, comments.* FROM articles, comments WHERE articles.uniqueuserid = $userId AND comments.postId = articles.Id ORDER BY articles.date_published DESC
Ofc all table and field names are would need adjustments to fit with your code.
What it does, is basically it loads all articles with uniquepostowner or whatever your name is and corresponding comments sorted by publish date.
Is this what you are after?
EDIT
Actually, comments and articles are spearate, and you want to display them side by side? In that case why don't you create 'events' table, which holds the date, the owner, the type (article/comment/like/photo/anything) and id of corresponding item and use that to generate your feed?

How can I select highest score the correct way in MYSQL?

I'm trying to accomplish:
selecting top 20 highest score users with the least SQL / PHP way possible.
caching is still not been considered for now.
What I've done so far:
I'm able to retrieve all 5k+ records with their scores, but not able to limit to only retrieve or calculate top 20(example).
Tables:
users (id, name)
score_rec (id, uid, points) This table has multiple entries for each user. Highest scores will be the ones which has highest amounts of rows, entries. Example: UID 23 could have 5 rows which belong to it, his score is 5.
Code Sample:
$query = "SELECT * FROM score_rec,users where users.id = score_rec.uid";
$result = mysql_query($query);
$array1 = Array();
while($row = mysql_fetch_array($result) )
{
//Count their scores
$query2 = "SELECT users.id,users.name,score_rec.uid FROM `score_rec`,`users` where score_rec.uid = $row[uid] and users.id = $row[uid]";
$result2 = mysql_query($query2);
$scores_count = mysql_num_rows($result2);
$array1["$row[name]"] = $scores_count;
}
I'm thinking this might be possible with maybe a temporary table script, stored procedure, or simple query which could look at both tables. Since scores_rec could be used by itself to calculate higuest entries holders, maybe one query could suffice to both tables.
Thank you all for any direction given.
What about something like this :
select users.id, count(*) as score
from users
inner join score_rec on users.id = score_rec.uid
group by users.id
order by count(*) desc
limit 20
This will :
For each user, count how many rows he has (because of the group by)
sort all users by number of rows -- in descending order
keep the first 20 resulting rows -- which are the 20 users who have the bigger number of rows
$query = "
SELECT users.id,users.name,count(*) score
FROM score_rec
INNER JOIN users on users.id = score_rec.uid
GROUP BY users.id,users.name
ORDER BY score DESC
LIMIT 20
";
$result = mysql_query($query);
$array1 = Array();
while($row = mysql_fetch_array($result) )
{
$array1["$row[name]"] = $row['score'];
}
Depending on how you want your scores:
1) global top 20 scores, possibly repeating users:
SELECT users.id, users.name, score_rec.points
FROM users
LEFT JOIN score_rec ON users.id = score_rec.uid
ORDER BY score_rec.points DESC;
2) scores of the top 20 distinct players:
SELECT DISTINCT users.id, ...
etc...

Categories