Get users position between friends - php

I'm trying to get a users position between the users friends, but I don't have any idea of how I can do this...
I have two tables.
Table 1: friends (where all the users friends are listed)
Table 2: users (where all the users are listed)
I want the query to check the users position between his friends.
So if I, for example have ID 1 (with 100 credits) and a friend with ID 2 (with 21 credits), the query would list my position as 1.

You don't really provide much information on your table layout, so it's going to be impossible for me to provide a very specific example. I'm also afraid I don't really understand your question, but I'll give it a shot...
First, I'll assume your users table has at least these columns:
id (PK)
credits
And that the friends table has these columns:
user (FK to users.id)
friend (FK to users.id)
Now, if I understand your question, you want to rank all of a user's friends, based on how many credits they have, so:
SELECT u.id,u.credits
FROM friends AS f
JOIN users AS us ON f.friend = u.id
WHERE f.user = 1
ORDER BY u.credits DESC;

in order to get the position I would recommend using PHP for this and not try to put it all in one query. So get a sorted list like Flimzy described and get the position by using an array function like array_search.

Related

Mysql query with multiple tables and foreign keys

Consider this mysql tables structure (useful to store private/group chat messages):
USERS
user_id
username
password
GROUPS (= DISCUSSIONS / TOPICS)
group_id
name
GROUPS_MEMBERS (= MEMBERS OF A SPECIFIC DISCUSSION / TOPIC)
group_id
user_id
MESSAGES
message_id
timestamp
from_user_id
destination_type (enum - group, user)
destination_id
Can you please help me with the query to retrieve the list of the 5 more recent dicussions (either private or group) in which a specific user has been a active?
Important:
I don't have actual code since I'm just deciding how to structure the database tables. The table structure presented above it's pretty self-explanatory (destination_id is a reference to group_id, and group members are all the users that will receive a message. Finally, all messages sent between the users of a specific group make a discussion or topic).
Here is what I want to do (it's very easy... don't over-think it... it's like any chat/messaging system like Facebook or Gmail etc).
When a user logs in and opens the chat he will of course see all the latest discussion which he is/has been a part of. In a chronological DESC order.
So I need to write the query to retrieve the latest 5 GROUP_IDs (= discussions) in chronological DESC order. But only the discussions which the logged-in user is a part of.(Of course I have the id of the logged-in user.. for example 16)
P.s. I didn't build this table structure myself but it seems logic; the only problem is the one presented above.
Here's my suggestion. You can get different records by using DISTINCT and get only five records by using LIMIT. You can replace logged_in_user_id with the login id.
SELECT DISTINCT GROUPS.group_id FROM USERS
JOIN GROUP_MEMBERS ON USERS.user_id = GROUP_MEMBERS.user_id
JOIN GROUPS ON GROUPS.group_id = GROUP_MEMBERS.group_id
JOIN MESSAGES ON destination_type = 'group' AND destination_id = GROUPS.group_id
WHERE USERS.user_id = logged_in_user_id
ORDER BY timestamp DESC
LIMIT 5;
#Igor Carmagna:
I have gone through your question and according to that i think you are required list the top 5 messages which have been left by the end users right ?. So for that please please follow below given steps.
1) First and for most thing you are required to do is that Join.
2) In this step you are required to use max() function which will give you list of the users on the base of messages received. Now, according to your question you are required to have only top 5 records so you are bound use (max-5) function this will given top 5 records
Hope this will make you day !!
Cheers :) :P

Compare and Extract Remaining Records List Php Mysql

Hi All I am working on a friends system like facebook I have following tables:-
Table users
id
username
email
password
datecreated
etc....
Table friends
id
user1
user2
datemade
my questions are as follow:-
How to fetch records (users list) not in friends table (user id not in friends table). for example :-select * from users not in friends table
How to compare users id with other two fields in friends table user1 or user2
Question 1.
SELECT * FROM users WHERE id NOT IN(SELECT id FROM friends)
Please provide the clear description of the table names and their corresponding column names and properties.
As per my understanding, below is probable solution.
1) select * from users u, friends f where f.user1="xyz" and f.user2<> { select user1, user2 from friends where user1 = "xyz" or user2="xyz"};
Note: I haven't tested the above query. If any error post it will try to rectify.
2) first of all there needs to be some connection between the two tables i.e. primary key and foreign key and also needs normalisation then the comparison can be made. From the above tables there is no common factor between the two tables, so comparison cannot be made. (I thinking that id in both table are different.)
Following are the answer for your queries :-
1. For the first question you have to use the following query. i.e SELECT * FROM users WHERE id NOT IN (SELECT id FROM friends)
Hope it will solve your problems. Looking forward for comments if anyThanks.

Achievements in PHP with mysqli

I've currently got two tables:
mems (members):
id,
name,
email,
password,
salt,
achievements_id
achievements:
id,
achievement,
description,
points
I am able to correctly display the data for a user with:
"SELECT * FROM achievements WHERE id IN (SELECT achievements_id FROM mems WHERE name = '$name')";
My question is, how do I add the achievement ID to the user so each user has their own achievement records? Currently if I use an update it just wipes over the old achievement so it only ever displays 1 record.
Say I have 2 achievements and 2 users
User 1 achieves achievement 1, it's viewable and they have achievements_id set to 1.
User 2 achieves achievement 1, it's viewable and they have achievements_id set to 1.
User 1 then achieves achievement 2, it's viewable but now they have achievements_id set to 2.
I have no clue how to do this. I know what I want to do, but no clue how to design the database to have each user having their own records of achievements.
I originally did it where achievements table had a member_id and I'd concat the other users ID into their, dodgy but it semi-worked.
Any help? Sorry if I am making no sense.
It sounds like what you need is to model a many-to-many relationship (many users can share the same achievement - ie. be linked to the same entitiy in the achievements table; while a single user can have multiple achievements). This is usually done using an extra table. Let's call it: Members_Achievements_Map.
CREATE TABLE Members_Achievements_Map (
MemberID,
AchievementID
)
This table would link entities from the members table to entities in the achievements table.
The way I would go about this would be to create another table to hold the users achievements.
So basically another table that looks like such:
UserAchievements:
userID, achievementID
That way you can join the tables like:
SELECT * FROM achievements a
INNER JOIN userAchievements uA ON uA.achievementID = a.id
INNER JOIN users u ON uA.userID = u.id
That will give you all the users for all the different achievements.
Hope that helps!

Using an array in an SQL query

Okay, so I want to have a news feed on my website. I have 3 tables named Users, Follow, and Posts. Basic user data goes into the Users table, who is following who is stored in the Follow table, and whatever the user posts goes into Posts. Now, I know how to select every post from a database table and limit it using the WHERE clause. But how would I write my query to select all all of the posts from only user's they are following, and display them by DESC date? Thanks.
Here's a general layout for you, make three tables like you mentioned, I've outlined below just as an example
[TABLES]
users
followers
posts
In the users table you should have at least columns like userid (auto incremented value / primary key).
The followers table should have something like userid which would match to the users table userid, a followid column which would also have the id # for the follower from the users table.
Then for your posts table you would want to have userid too so when each post is made it would have the id from users table.
Then you would need to do something like:
SELECT p.*
FROM posts AS p
WHERE p.userid IN (SELECT followid FROM followers WHERE userid = ###)
ORDER BY p.date DESC
Now it really depends on how you are getting the users id to figure this out. If your passing the users id using a session after they logged in similar to something like Facebook, then you could change userid = ### to something like userid = ".$_SESSION['userid']." But again it really depends on how you pass the users id but the above should at least get you somewhat started.
Make sure to put indexes on the userid, followid columns so that when the table becomes larger it will do the joins quickly.
An alternative to #Shane's answer is to use the JOIN operator:
'SELECT p.* // I prefer to name all the fields, but for brevity's sake I'll use the shorthand
FROM Posts AS p
INNER JOIN Follow AS f ON p.userid = f.followid
WHERE f.userid = '.$selectedUserID.'
ORDER BY p.date DESC;'
For an inputed User ID ($selectedUserID), it will find all User ID's of the people they follow (matching follow ID to user ID on the Follow x-ref table) and then find their respective posts from the Post table in descending order by date. It will return empty if they do not follow anyone or the people they follow have no posts.
I also hope I do not need to remind you to sanitize your input to the database and escape your output to the web.
Is this what you're looking for?

Friend of a friend in PHP/MySQL?

I have a social network similar to myspace/facebook. In my code you are either a person's friend or not a friend, so I show all actions from people you are friends with (in this post I will refer to actions as bulletin posts alone to make it easier to visualize.
So you every time a person post a bulletin it will show up to any person who is there friend.
In mysql you would get a persons friend list by doing something like this,
SELECT user_id FROM friends WHERE friend_id = 1 (user ID)
I want to know how a site like facebook and some others would show all bulletin post from your friends and from your friends' friends?
If anyone has an idea please show some code like what kind of mysql query?
The answer is that they aren't doing selects on a friend table, they are most likely using a de-normalized news-event table. We implemented a news-feed similar to Facebooks on DoInk.com, here's how we did it:
There is the notion of a "NewsEvent" it has a type, an initiator (a user id) and a target user (also a user id). (You can also have additional column(s) for other properties relevant to the event, or join them in)
When a user posts something on another users wall we generate an event like this:
INSERT INTO events VALUES (wall_post_event, user1, user1)
When viewing user1's profile, you'd select for all events where user1 is either the initiator or the target. That is how you display the profile feed. (You can get fancy and filter out events depending on your privacy model. You may consider doing this in memory for performance reasons)
Example:
SELECT * FROM events WHERE initiator = user1 or target = user1 //to see their profile feed
SELECT * FROM events WHERE initiator IN (your set of friend ids) //to see your newsfeed
When you want to see the newsfeed for all events relative to your friends you might do a query selecting for all events where the initiator is in your set of friends.
Avoid implementations with sub-selects, depending on the complexity, they will not scale.
you do a subquery:
SELECT DISTINCT user_id FROM friends WHERE friend_id IN
(SELECT user_id FROM friends WHERE friend_id = 1)
Test both of these for performance:
SELECT DISTINCT user_id
FROM friends f1
JOIN friends f2 ON f1.friend_id = f2.user_id
WHERE f2.friend_id = 1
and
SELECT DISTINCT user_id
FROM friends
WHERE friend_id IN (SELECT user_id FROM friends WHERE friend_id = 1)
Often they're the same but sometimes they're not.
Make sure friend_id and user_id are indexed.
The simple approach would be to do some kind of simple nested clause. So say you have a table with posts and the posters id, and a friends table, the first layer would be
SELECT post FROM posts JOIN friends
on post.userid = friends.friend_id
WHERE friend.id = 1 (user ID)
then to get a friends of friends
SELECT post FROM posts JOIN
(SELECT DISTINCT friends_2.friend_id FROM friends AS friends_1
JOIN friends as friends_2
on friends_1.friend_id = friends_2.id where friends_1.id = 1)
AS friends
wHERE post.userid = friends.friend_id AND mainid = 1 (user ID)
You can repeat this nesting each time you want to add another layer of friend abstraction. The problem with this approach is that it would take a very long time to execute. For every time you add a layer of friend abstraction you are increasing the complexity by a power of n (where n is the number of rows in your table).
It is more likely that they are saving the viewable friends in a table somewhere, so lets make a new tabled called friends_web
user_id, friend_id, level
when a user friends someone, it adds that new friend into friends_web at a level of 0(since that friend is no people away) then adds that friends friends at a level of 1 (since its 1 friend away). In order to keep the table integrity you would also want to add the inverted record. To clarify if A adds B as a friend and C is a friend of B, the following two records would get added to our new table
A, C, 1
C, A, 1
since now A can see C and C can see A.
now when we want a query we just do
SELECT post FROM posts
JOIN friends_web ON post.user_id = friends_web.friend_id
WHERE friends_web.user_id = user_id AND friends_web.level < 2 (or however deep you want to look)
by doing that you minimized your query complexity when doing post lookups while being able to look more then 1 layer deep into a friend web.
Sorry for the long winded response.
This should pull out all the user's friend's posts.
SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1) ORDER BY post_id DESC
This should pull out all posts that are your friend's friend's.
SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1)) ORDER BY post_id DESC

Categories