My table scheme for a social network site is as follows:
users
id|username
1|bob
2|mary
3|ken
userinfo
id|userid|handle|description
1|1|bobbie|student
2|2|Mary1|programmer
network
id|inviterid|invitedid|status
1|1|2|2
2|1|3|2
When one person invites another to join his/her network, an entry is made into the network table with status 1. If the request is accepted, the status goes to 2. So far so good.
However, I'm having trouble listing out members of someone's network while joining with other tables since in effect I have to join on more than one field since the person can either be the inviter or the invited.
Here is query to get members of network
//$id = id of logged in user
$sql = "SELECT * FROM `network` n
LEFT JOIN `userinfo` ui
on n.invitedid= ui.userid OR n.inviterid = ui.userid
LEFT JOIN`users` u
on n.invitedid= u.id OR n.inviterid = n.id
WHERE status='2'
Not all users have userinfo records as not everyone has filled out a profile. But I want to get these as well.
Results of Query for Bob's network ie $id=1:
Bob student
Mary student
Bob programmer
Mary programmer
Note it includes bob even though he should be excluded, uses Bob's info for Mary and excludes Ken cause he has no userinfo record.
Above query gives multiple records for users with profiles, records for the logged in user and excludes any without profile. I want to exclude logged in user and then one record for each member of his/her network including members without profiles.
Update:
changing WHERE to following excludes user's own profiles which helps a bit but still excludes members without profiles:
WHERE status = '2' AND ui.userid <> '$id'
Thanks for any suggestions.
Try this:
$sql = "SELECT * FROM `network` n
LEFT JOIN `userinfo` ui
on n.invitedid= ui.userid OR n.inviterid = ui.userid
RIGHT JOIN`users` u
on n.invitedid= u.id OR n.inviterid = n.id
WHERE status='2'
Related
So I am looking to extract data from various tables. the tables are joined together but currently I am seeing many duplicates.
Here are the tables I am using:
courseuser: gets the course information for a user
user: gets user information (username)
course_session: provides the sessions for a course (1 course can have multiple sessions)
courseuser_session: provides information showing which user id is connected to which session id (1 user can have 0 or more sessions associated, this table would only show a record if there is a minimum of 1 session associated to a user)
This is my query so far:
SELECT
u.userid as User_id,
u.user as Username,
lcu.courseid as Course_id,
lcus.sessionid as Session_id
from courseuser lcu
LEFT JOIN user u ON lcu.id = u.id
LEFT JOIN course_session lcs ON lcu.courseid = lcs.courseid
LEFT JOIN courseuser_session lcus ON lcs.sessionid = lcus.sessionid AND lcu.userid = lcus.userid
where u.userid = '205069';
sorry if the data in the tables doesnt format well
sample data:
courseuser:
userid
courseid
additional data not associated..
205069
8
-
205069
47
-
user:
userid
user
additional data not associated..
205069
Tim
-
course_session:
sessionid
courseid
additional data not associated..
70
8
-
10
8
-
66
8
-
courseuser_session:
sessionid
userid
additional data not associated..
70
20569
-
The user 205069 is only on 1 session for 1 course.
The above sql query returns all of the other sessions for that course also even though the user is not on it.
I would like an output where it shows only the session the user is on AND
because some courses do not have sessions, I want to show the courses also which are associated to the user, it can fill the session column with NULL if it does not exist.
Replace this line
LEFT JOIN courseuser_session lcus ON lcs.sessionid = lcus.sessionid AND lcu.userid = lcus.userid
by this one
INNER JOIN courseuser_session lcus ON lcs.sessionid = lcus.sessionid AND lcu.userid = lcus.userid
I have a table that maps User and Feature. Basically what features are enabled for each user. The table is |userId|featureId| with one(user) to many(feature) relationship.
I would like to create a query that takes a list of userIds and returns the list of userIds that are missing a specific feature.
Meaning I need to make sure that every id has a specific featureId.
userId featureId
1 A
1 B
2 A
3 C
4 D
3 A
So in this example, I'll get the list of ids (1, 2, 3, 4) and a featureId A and the query will return one row with userId 4 since it's the only userId with the feature A enabled.
To find a list of users that don't have feature X I would left join to the list of users that has that feature and return the ones not there. Like this:
SELECT *
FROM table_you_did_not_name as base
LEFT JOIN (
SELECT DISTINCT userID
FROM table_you_did_not_name
WHERE feature = 'X'
) as sub ON base.userID = sub.userID
WHERE sub.userID is null
I think I may have answered a different question: this doesn't address your data; but I'm unsure how you determine it is user 4 you want returned. as each user is missing some of the features the others have. Perhaps we just need to add a where clause below for the specific feature(A) in your example?
Think of data in terms of sets
You need
a set of data for all users (User or something)
a set of data for all features (feature)
and what features a user has (User_Feature)
Then you need to
Generate a set of every feature to every users (cross join)
Identify which of those the user has identified. (left join in user_feature)
and then only keep those where no feature has been identified (where no record in user_feature)
One method: This basically says return the features for each user that exist in a feature list, but have not been associated to a user.
SELECT U.userID, F.FeatureID as FeatureIDMissing
FROM USER U
CROSS JOIN FEATURE F
LEFT JOIN UserFeature UF
on U.UserID = UF.UserID
and F.FeatureID = UF.FeatureID
WHERE UF.UserID is null
-- and F.FeatureID = 'A' --maybe add this?
Alternate method: (combine two steps (2,3) by simply excluding those features which already exist for the user.
In english this says, return all the features for each user for which a user has not been associated
SELECT U.userID, F.FeatureID as FeatureIDMissing
FROM USER U
CROSS JOIN FEATURE F
WHERE not exists (SELECT *
FROM userFeature UF
WHERE U.UserID = UF.UserID
and F.FeatureID = UF.FeatureID)
--and F.FeatureID = 'A' --maybe add this?
Either answer should return the same results. It's a matter of preference database and performance .. Look at the execution plans to help decide which is best for you and your data.
Now maybe you mean you give a list of userID's you want to generate a unique set of features for all those users, and then return users w/o those features. If so instead of a cross join to feature you just need to use (Select distinct FeatureID from userFeatures where UserID IN ('yourListHere') this will generate a unique set of features for those users and identify which users are missing certain features shared with that set of users.
So...
SELECT U.userID, F.FeatureID as FeatureIDMissing
FROM USER U
CROSS JOIN (SELECT distinct FeatureID
FROM userFeatures
WHERE UserID IN ('yourListHere')F
LEFT JOIN UserFeature UF
on U.UserID = UF.UserID
and F.FeatureID = UF.FeatureID
WHERE UF.UserID is null
-- and F.FeatureID = 'A' --maybe add this?
as an example.
Say I have a MySQL table photo with two columns: "url" and "owner_id." I have another table unfollowed_user with two columnts: "unfollower" and "recipient."
I'm trying to create an O(n) MySQL query that selects all of the photos from the photo table for a particular site user but excludes any photos with by owners that the user has "unfollowed."
Here's what I've tried so far:
SELECT p.url FROM photo p LEFT JOIN unfollowed_user u ON
p.owner_id = u.recipient WHERE recipient IS NULL;
This does indeed return any photos and exclude any by an owner that has been unfollowed, but it excludes all photos by an owner that any user has "unfollowed," not just when a specific user has unfollowed.
So how about:
SELECT p.url FROM photo p LEFT JOIN unfollowed_user u ON
p.owner_id = u.recipient WHERE recipient (IS NULL OR unfollower != ?);
(supplying a particular user for the ?)
This returns duplicate results, because it creates a new row if other users (not our particular user) has unfollowed the photo owner. If users 1 and 2 have unfollowed user 10, user 3 will get any of user 10's photo twice because there are two rows in which the unfollower != 3.
So how about adding a SELECT DISTINCT:
SELECT DISTINCT p.url FROM photo p LEFT JOIN unfollowed_user u ON
p.owner_id = u.recipient WHERE recipient (IS NULL OR unfollower != ?);
This fixes the duplicate entry problem, but raises another problem. Say users 3 and 4 have both unfollowed user 10. Any photos by user 10 will be left out the first time around because user 3 has unfollowed user 10. However those photos will also be included because someone who is not user 3 has unfollowed user 10.
OK, OK. I know the obvious choice is
SELECT p.url FROM photo p WHERE owner_id NOT IN
(SELECT recipient FROM unfollowed_user u WHERE unfollower = ?);
But for large data sets, this has O(n^2), right? MySQL is subquerying every photo's owner?
Any help, pointers, helpful articles or blog posts, etc, would be appreciated.
I'm doing a microblogging site (like Twitter) using a mySQL database. In that database I have three tables: one for users, one for messages and one to control who follows who. When the user enters the site I want to show his own messages and those from the people who he follows, so I use this query:
SELECT * FROM messages
INNER JOIN users ON users.id = messages.author
INNER JOIN followers ON followers.main_user = 2
WHERE messages.author = followers.followed_user OR messages.author = 2
ORDER BY date DESC;
Being '2' the user that's entering the site.
The thing is that I get the messages written by the person who enters (2, in this example) twice, and once from the people he follows. Does anyone have a clue about how to solve this? User 2 doesn't follow himself.
I'm a beginner in queries and I'm struggling with one of them. Here are the two tables involved :
The askstobefriends table permit a user to add a friend in the application I m developping. The relational form of it is :
AskToBeFriends(ID (long), #UserAsker (long), #UserAsked (long), Accept (tinyInt))
So with this table we can see who asked to be friend and if it was accepted ...
The query I m trying to realize would permit to list all the user's friends from his ID and also return the friendship statut (accept field ==> waiting for an answer, accepted or refused).
Speretaly, it would be something like that :
SELECT Accept, UserAsker, UserAsked
FROM askstobefriends
WHERE UserAsker = '".$userID."' OR UserAsked = '".$userID."' ";
==> first issue : it can either be the user who asked to be friend with someone or the opposit, that why i've put and OR. After that, I d like that for everyfriend founded there's these informations :
SELECT colUserID, colUserLogin, colUserName, colUserFirstname
FROM userTable
WHERE colUserID == FRIEND
So I guess I need to do a join query, and in my join I have to be sure that I'm using the right foreign key from the asktobefriends tablefor each cases !! (once the key could be UserAsked and another time UserAsker depending on who asked to be friends :S )
Does anyone have a clue please :S ?? Thanks ;-) !!
Your design is wrong. A User asks to be friend of another User, so "Ask_to_be_friend" is the relation, and the cardinality is many to many, so the design will looks like this:
User_User_ID is UserAsker.
User_USer_ID1 is UserAskedtobefriend
and the query could be like (you'll get all the users that user_user_ID Asks to be friend of):
Select U.* from User as U
Join Ask_to_be_friend as A on
U.user_ID = A.User_user_ID
--where a.accept=1 if you add this, this will give
--you all the friends ID of the user_ID table User
If you want to get the names or extra info of the askedtobefriend you'll need a extra Join
Select U.* from User as U
Join Ask_to_be_friend as A on
U.user_ID = A.User_user_ID
Join User as U2 on
A.User_User_ID1=u2.User_ID
--where a.accept=1 ,with this you'll with get only the friends
You could join the tables using criteria that ensure only friends of :userID are returned. For example:
SELECT u.*, a.Accept
FROM askstobefriends a JOIN userTable u ON (:userID, u.colUserID) IN (
(a.UserAsker, a.UserAsked),
(a.UserAsked, a.UserAsker)
)