php mysql join multiple table - php

I have two table
User
userID username email
1 abc abc#abc.com
2 def def#def.com
3 ghi ghi#ghi.com
Referral
refID userID invEmail
1 1 abc#def.com
2 1 omg#mog.com
3 1 def#def.com
So what i plan is to give a invited user 5 point meanwhile a inviter 10 point, so basically userID 1 gained 30 meanwhile userID 2 gained 5. The point i can do in PHP but one part i faced difficulty is when a invEmail to be identified. I don't mind separating into multiple queries if its will work.
How do i show this in sql?
I tried something like
SELECT *, count(r.userID) FROM user u, referral r WHERE u.userID = r.userID OR u.email = r.invEmail GROUP BY r.userID
It returned wrong value.
What i would like it to return, how much count is there inviter and invitee(matched email who has registered based on inviter invitation)
How should i do it?
Thank you.
Edit: i forgot to add something into question, what if i wanted the inviter to receive 10 points only if invitee registered? what i meant is that, only if invEmail exists in u.email then only userID received 10 point. Sorry for my mistake.

You might be able to do something like this:
select points.userId, points.username, points.email, sum(points.points)
FROM
(select u.*, count(*)*10 as points
from user u
join referral on u.userID = r.userID
join user verify_user on r.invEmail = verify_user.email
group by u.userID, u.username, u.email
UNION
select u.*, count(*)*5 as points
from user u
join referral on u.email = r.invEmail and u.userID != r.userID
group by u.userID, u.username, u.email
) as points
group by points.userId, points.username, points.email
I think you need two separate selects to get the points for each type of registration, combined with a union statement.

Related

PHP mySQL retrieve unique correct data from multiple tables

So i am making this webpage (for fun to practice web dev) where users can rate or comment on a movie. One page I have is where you click on the movie for full details and it lists all the ratings and comments (together if the user has commented by review and rated through a page called "reviewMovie"...which if they went this way the rating is mandatory, otherwise they can comment on this page "listMovieReviews").
The problem I am having is incorrect details when doing my queries
the discussion table stores: the discussion ID (primary key) the timestamp of the
comment, the comment, the user who made the comment, and the movie they commented
about.
the discussion table stores: the discussion ID (primary key) the timestamp of the
comment, the comment, the user who made the comment, and the movie they commented
about.
the rating table stores: the rating ID (primary key), the movie being rated, the
user who did the rating, and the rating score (out of 10)
So some examples of the combined data are:
User1 (user1) has rated "American Psycho" a 4/10 and has made a comment "comment1" on
it
User2 (admin..for testing purposes) has rated "American Psycho" a 8/10 and has made a
comment "comment2" on it
So on the page that lists the details of "American Psycho" and the ratings/comments I should have this list of ratings and comments:
<TIMESTAMP FOR COMMENT1> User1 Rating 4/10 "comment1"
<TIMESTAMP FOR COMMENT2> admin Rating 8/10 "comment2"
Using the following queries:
SELECT *
FROM discussion
INNER JOIN users ON discussion.userID = users.userID
WHERE discussion.movieID = <American Psycho's Movie ID>;
AND
SELECT *
FROM ratings
INNER JOIN movies ON ratings.movieID = movies.movieID
WHERE ratings.movieID = <American Psycho's Movie ID>;
I get this:
<TIMESTAMP FOR COMMENT2> admin Rating 4/10 "comment2"
<TIMESTAMP FOR COMMENT2> admin Rating 8/10 "comment2"
I have tried several other INNER JOINS with joining the table that stores user information and table that stores movies information but I keep getting mixed data
Also tried DISTINCT and UNION but still to no avail
Where am I going wrong??
Also first post so sorry If I have not been too clear, bad formatting, or not shown enough work but I am really really stuck
I assume:
A movie could have from 0 to n comments.
A movie could have from 0 to n ratings.
A user could rate a movie only once or none.
A user could comment a movie from 0 to n times.
Your queries are fine, maybe your problem is in your php code.
You have to account that a user maybe comment a movie several time and never rated it.
In second query you should JOIN with user (instead of with movie, because you do not get movie information) to get the user name.
Maybe you should display the info in two table: one for ratings and other for comments.
(You have to replace quotation marks by movie ID)
SELECT u.userName, r.score
FROM ratings AS r
INNER JOIN users AS u ON r.userID = u.userID
WHERE r.movieID = ?;
SELECT u.userName, d.commentTime, d.comment
FROM discussion AS d
INNER JOIN users AS u ON d.userID = u.userID
WHERE d.movieID = ?;
You could group all comments per user in one row this way (but I think this is not what you are looking for):
SELECT u.userName, GROUP_CONCAT(CONCAT(d.commentTime, ': ', d.comment) SEPARATOR '; ') AS comments
FROM discussion AS d
INNER JOIN users AS u ON d.userID = u.userID
WHERE d.movieID = ?
GROUP BY u.userName
I think do not have sense to make one query in this case, but if you want get all data in one query you could try something like this:
You will have a comment per row, so for example if a user make two comment you will have two rows for the same user with the same score.
First I get all user that comment or rating the selected movie and make a CROSS JOIN between movie and these users. Then I make a LEFT JOIN with discussion ON movieID and userID and another LEFT JOIN with ratings ON movieID and userID.
You need to make LEFT JOIN instead of INNER JOIN because if a movie do not have ratings or comments your result will be empty.
In SELECT clause you should list only the columns that you need.
SELECT *
FROM movies m
CROSS JOIN (SELECT d.userID
FROM discussion d
WHERE d.movieID = ?
UNION
SELECT r.userID
FROM ratings r
WHERE r.movieID = ?) AS u
LEFT JOIN discussion AS d ON m.movieID = d.movieID AND u.userID = d.userID
LEFT JOIN ratings AS r ON m.movieID = r.movieID AND u.userID = r.userID
LEFT JOIN users ON u.userID = users.userID
WHERE m.movieID = ?;
You need to join all three tables.
SELECT *
FROM movies AS m
JOIN ratings AS r ON r.movieID = m.movieID
JOIN discussion AS d ON d.userID = r.userID AND d.movieID = m.movieID
WHERE m.movieID = <American Psycho's Movie ID>
ORDER BY r.userID, d.timestamp
This will repeat the movie and rating information for each comment. You can remove those duplicates in the application code that displays the results. See How can i list has same id data with while loop in PHP? for an example of how to do this.
SELECT * FROM movies AS MOVIE
JOIN ratings AS RATING ON `RATING.movieID` = `MOVIE.movieID`
JOIN discussion AS DISCUS ON `DISCUS.userID` = `RATING.userID`
WHERE `MOVIE.movieID` = <SOME Movie ID>
ORDER BY `RATING.userID`, `DISCUS.timestamp`

PHP multiQuery issue

I'm having a bit of an issue regarding multi-querying with PHP. My database has the following tables, with their schema shown below:
First table - Users
(PK) UserID,
UserFullName
UserID FullName
1000 Arthur Whitney
2000 Alex Schwartz
3000 Eva Kilpatrick
Second table - Invites
(PK) RowID,
InvName, InvSender, InvSenderTotal, InvReceiver, InvReceiverTotal, InvStatus
RowID InvName InvSenderID InvSenderTotal InvReceiverID InvReceiverTotal InvStatus
1 Fair 1000 10 2000 10 Sent
2 Party 2000 45 1000 45 Sent
3 Cinema 2000 12 1000 12 Sent
4 Vacation 3000 15 1000 5 Expired
Say for example when user Alex Schwartz, with unique ID 2000, is logged in, I would like to have it that he can see the name of the invite, the invite sender's name (if he is the invite receiver), the invite receiver's name (if he is the invite sender) and both the invite sender and receiver's totals.
I have devised the following two queries, which yield the results that I intended:
QUERY1
select i.InvName, i.InvSenderTotal, i.InvReceiverTotal, u.FullName FROM Invites as i INNER JOIN Users as u ON u.UserID = i.InvReceiverID
WHERE i.InvStatus = 'Sent' AND i.InvSenderID = 2000
This shows me the Invite Name, Invite Sender and Receivers' totals and the Invite Receiver's name when Alex Schwartz was sending the invite. Expected output here would be specific details of Row IDs 2 and 3.
The following query shows the inverse:
QUERY2
select i.InvName, i.InvSenderTotal, i.InvReceiverTotal, u.FullName FROM Invites as i INNER JOIN Users as u ON u.UserID = i.InvSenderID
WHERE i.InvStatus = 'Sent' AND i.InvReceiverID = 2000
So this enables Alex Schwartz to see the name of the person who sent the invite, along with the same data. Expected output here would be specific details of Row ID 1.
Hence, I am able to get the data I want, but I require two different queries in order to get it. This has presented problems in PHP whereby only one query seems to carry out. So my question is essentially, does anyone know how I could combine these two queries into one? I am also aware of multiQuerying and have tried to implement this, but have not had much success with that either.
Thanks in advance of your help.
Why not use UNION.
select i.InvName, i.InvSenderTotal, i.InvReceiverTotal, u.FullName FROM Invites as i INNER JOIN Users as u ON u.UserID = i.InvReceiverID
WHERE i.InvStatus = 'Sent' AND i.InvSenderID = 2000
UNION
select i.InvName, i.InvSenderTotal, i.InvReceiverTotal, u.FullName FROM Invites as i INNER JOIN Users as u ON u.UserID = i.InvSenderID
WHERE i.InvStatus = 'Sent' AND i.InvReceiverID = 2000
As a note, you can do this without union all (which is preferred over union unless you intentionally need to remove duplicates):
select i.InvName, i.InvSenderTotal, i.InvReceiverTotal, u.FullName
FROM Invites i INNER JOIN
Users u
ON u.UserID IN (i.InvReceiverID, i.InvSenderID)
WHERE i.InvStatus = 'Sent' AND i.InvSenderID = 2000;

MySQL count in "complex" SQL query

I have the following SQL query: Let me describe it to you quickly. I wanna develop a soccer tip game. I have 4 tables: apps, tips, users, games.
Relations:
apps 1 to N users
user 1 to N tips
game 1 to 1 tip
Instead of listing all games where the User had a successful tip, I just want to list the u.userId with the COUNT of successful tips. Check out my SQL:
SELECT
t.*, u.*, g.*
FROM
tips AS t,
users AS u,
games AS g
WHERE
u.userAppId = 4 AND
t.tipUserId = u.userId AND
g.gameResult = t.tipGameResult
I guess I somehow have to implement a COUNT and u.userId instead of
t.*, u.*, g.*
but I am not 100% sure how to do it. Do you have any suggestions?
SELECT
u.userid, count(*)
FROM
tips AS t,
users AS u,
games AS g
WHERE
u.userAppId = 4 AND
t.tipUserId = u.userId AND
g.gameResult = t.tipGameResult
group by u.userid
As mentioned in comment below, the group by on user id will give you
userid|count(*)

Advice on MySQL JOIN

I am struggling to get me head round the MySQL Join function.
Here is two tables I have:
User table:
admin_id username
*1 peter93
2 stackoverflowrocks
3 user3*
Admin details table:
admin_username description image
pedro93 [text] [image_url]
stackoverflowrocks [text] [image_url]
user3 [text] [image_url]
I know usualy to link two databases together you would use ID numbers, but in this case I want to join the two tables where admin_username = username.
Can anyone help me please? It is for a PHP script if that helps.
Thanks in advance!
Peter
So that's fine. You can join on anything you like.
select *
from user
inner join admin
on user.username=admin.admin_username
joining by a string column is the same as joining by Id
select * from admin_table
inner join admin_details on admin_table.username = admin_details.admin_username
But make sure you have and index for the username columns, or else your queries will go slow when you have lots of records
You can join on pretty much any field but you may wish to keep in mind datatype mismatching, indexing etc
All users
SELECT u.*, a.*
FROM users AS u
LEFT JOIN admin AS a
ON u.username = a.username
All users that are admin
SELECT u.*, a.*
FROM users AS u
INNER JOIN admin AS a
ON u.username = a.username
All admin
SELECT u.*, a.*
FROM users AS u
RIGHT JOIN admin AS a
ON u.username = a.username

How to omit select results based on IDs from another table in mySQL?

My goal is that I want to get a list of user names in the database from my "users" table, but omit every user whose ID is also in the "projects_users" table where project_id = 1.
In another words, if these are the tables:
table: users
user_id user_name
1 dave
2 matt
3 james
table: projects_users
user_id project_id
1 2
2 2
3 1
This query would return "dave" and "matt" (since "james" is in the users table, but is also associated with project #1, thus he is omitted).
I understand that I should probably be using some form of join, but my current query is not doing it:
SELECT user_name
FROM users
JOIN projects_users ON (
users.user_id != (projects_users.user_id WHERE projects_users.user_id == 1)
)
This result does not work at all, and earlier experiments kept returning multiple copies of every name. Does anyone know of a way to do this without having to turn to a more manual PHP solution?
Final answer, worked perfectly. Maybe it isn't as optimised as some of the other solutions, but it's the only one that gave me valid results every time. For some reason, the other solutions sometimes popped out an unexpected name, or no name at all when they should have. Regardless, this sure beats doing it the long way with PHP.
SELECT user_id, user_name FROM users WHERE user_id NOT IN (SELECT user_id FROM projects_users WHERE project_id = 1)
Thanks everyone for your contributions. I appreciate all of your help and input.
Original answer
Utilize the power of a LEFT JOIN.
SELECT u.*
FROM users u
LEFT JOIN project_users pu ON u.user_id = pu.user_id
WHERE pu.project_id IS NULL OR pu.project_id <> 1;
Unlike JOIN (which is a shortcut for INNER JOIN), LEFT JOIN selects all rows from main table and their matching rows from joined table, BUT if the matching row is not found, a fake one is returned with all fields set to NULL.
Edit
When I re-read the question, it appeared to me that I got it wrong. If you want to filter out only users that are associated with a certain project, then this is a query to use.
SELECT DISTINCT u.user_id, u.user_name
FROM project_users pu
LEFT JOIN users u ON u.user_id = pu.user_id
WHERE pu.project_id <> 1;
try this:
SELECT DISTINCT
users.user_id,
user_name
FROM
projects_users
RIGHT JOIN
users
ON
users.user_id = projects_users.user_id
WHERE
projects_users.project_id <> 1
OR
projects_users.project_id IS NULL
Try the following:
select u.*
from users u
where exists (select null
from projects_users pu1
where u.user_id = pu1.user_id)
and not exists (select null
from projects_users pu2
where u.user_id = pu2.user_id and pu2.project_id = 1)
Alternatively:
select u.*
from users u
join projects_users pu on u.user_id = pu.user_id
group by u.user_id
having max(case when pu.project_id = 1 then 1 else 0 end) = 0

Categories