I want to create a database that can store the friends contact list as like social networking
what is the best way to design the database structure and easy to retrieve the contacts of friends using mysql.
I need solution for this, HELP ME
The best way to model heriarchical data depends on what operations you need to support. I would suggest that you read Bill Karwin's slides Models for heirarchical data for a comparison. See in particular slide 48 where there is a summary of the strengths and weaknesses of each approach.
However, I wouldn't regard friendship as a heirarchical structure. There will normally be loops: A is friends with B, B is friends with C, and C is friends with A. Instead you can create a contact table with two columns: user_id and friend_id which are foreign keys into the "users" table:
contact_list
------------------
user_id friend_id
------------------
1 2
2 3
3 1
To retrieve the contact list for a specific user id run this query:
SELECT friend_id
FROM contact_list
WHERE user_id = 1
Here I'm assuming that A being on B's contact list does not imply that B is also on A's contact list.
Related
I have a database table which contains recipe information, I then have a second table which contains user information and finally I have another table which is a junction table between the two containing recipe_id and user_id which is used to hold the user's saved recipes.
My tables look like this:
|user |
|user_id |
|user_name |
|user_email |
|user_password|
|recipe|
|recipe_id|
|recipe_name|
|recipe_descript|
|category_id|
| etc.|
|user_saved_recipes|
|user_saved_recipe_id|
|user_id|
|recipe_id|
|category|
|category_id|
|category_name|
I want to be able to SELECT recipes from the recipe table that are LIKE recipes from the user_saved_recipes table based on a particular user. If anyone could help me go about this I would be very grateful as I have been struggling to find a solution.
Basically I want to be able to get a list of recipes that are similar to those recipes the user has saved thus creating suggestions for the user.
This is what I have tried so far:
SELECT *
FROM recipe r
JOIN user_saved_recipes ur
ON r.recipe_id = ur.recipe_id
JOIN user u
ON ur.user_id = u.user_id
WHERE ur.user_id = 1;
I know I need a LIKE in there somewhere in order to return rows with a similar name but I am unsure of how to go about this as I only have recipe_id in the user_saved_recipes junction table.
Thanks!
Recipes that are "like" other recipes is a very vague request. You have to consider - and specify - how you will calculate "like" in this case. What are some typical use cases you wish to meet? e.g.
Consider that someone really likes rabbit as an ingredient;
"You may also like" suggestions from your software should include other rabbit recipes.
So matching on ingredients (particularly the "hero" ingredient) is very likely to part of your algorithm.
Similarly, if a person has saved several cakes in their favourites, then the category cake will likely be a useful part of that algorithm.
Basically you need to compute a rank you can apply to recipes not already in their favourites that share some characteristics with those within the favourites.
I am trying to register some users with basic details like username/email, password and their respective hobbies like reading, sports, dance etc and later on display users with similar hobbies. The current schema looks something like this.
Users
- id
- email
- password
- country
- hobbies_id
hobbies
- id
- user_id
- sports(values true/false)
- reading(values true/false)
- dance(values true/false)
Each hobby is placed as a column in hobbies table.
What will be the most optimized schema if I increase the number of hobbies from 3 to 20?
Also, can someone help me with a query to select users with similar hobbies/hobby? For example, if John likes reading and sports, and Kim likes sports and dance then they have sports as a common hobby.
Thanks in advance.
Following up on comments by #Madhur Bhaiya, I would adress this with 3 tables:
users
- id
- email
- password
- country
hobbies
- id
- name (sports, reading, dance, ...)
user_hobbies
- user_id
- hobbie_id
The users table is the master table for users (one record per user).
The hobbies table is the master table for hobbies (one record per hobby). When new hobbies are created, you do not need to create new columns, just add new rows.
The user_hobbies table maps users to hobbies: it contains one record for each user_id/hobbie_id tuple.
we can do with two solution ::
#GMB's solution
removed hobby table and save hobby data into user table only, in json data-type.
For this, I would recommend looking into Database Normalization. This issue should be solved by implementing the Third Normal Form (TNF). For this, you should remove hobby_id from the users table and remove user_id from the hobbies table. A normalized example of one solution to this problem would be to create a new table that uses user_id and hobby_id as a Composite Key. See below:
users:
- id
- email
- password
- country
user_hobby:
- user_id
- hobby_id
hobbies:
- id
- description
- type
In this situation, the user_hobby table would have a many to many relationship between users and hobbies. If a user has multiple hobbies, they will have multiple hobbies linked to their id in the user_hobby table, but each user and hobby should be listed only once in their respective tables.
I am creating a site where each registered user can store a list of contacts. It occurred to me that rather than storing the contacts in a table with user_id, contact_name, contact_email, it would be better to normalize it to prevent the same names/emails being stored multiple times. As a result, I now have 4 tables: users, names, emails and contacts where contacts contains user_id, name_id and email_id. Am I heading in the right direction, or am I complicating things needlessly?
Thanks for all the helpful responses to what I can see now is a pretty nebulous question. It may be a good idea to explain my reasoning.
In an example scenario, where there are 100 users, most of whom have joined though the recommendation of another user, there will be a large number of common email addresses shared by each users contact lists. However, johnsmith#email.com, may be known as John, J Smith, Johnny boy etc. by different users. If I understand the principles of normalization correctly (unlikely) the separation of user, contact name, and email address in to separate tables, should reduce duplicate entries significantly and make the database more efficient. In the example below, the Contacts table could contain the same email addresses multiple times.
So, to cut a long story short, is it better to have more entries than necessary in one table or several smaller tables without duplicate entries?
You're probably needlessly complicating things: I'd recommend one table for users, one for contacts and a join table to allow a many to many relationship between the two. If contacts are not shared between users it'd be acceptable to have the user id as a foreign key in the contacts table.
Hope this helps
You can do like this
1] User_info Table
User_Id | name
2] Contacts Table
Contact_Id | Contact_Name | Contact_Email
3] User_Contact Table
User_Id | Contact_Id
Can contacts have same email but distinct names, or vice-versa ? If not, i suggest two tables (users and contacts) linked by an associative table :
USERS
- userId
- userName
CONTACTS_USERS
- userId
- contactId
CONTACTS
- contactId
- contactName
- contactEmail
With foreign key constraints on userId and contactId you can achieve a robust linkage between the two tables, where each contact may be used by distinct users and where each user may have distinct contacts.
I have a database where users enter their interests. I want to find people with matching interests.
The structure of the interest table is
interestid | username | hobby | location | level | matchinginterestids
Let's take two users to keep it simple.
User Joe may have 10 different interest records
User greg may have 10 different interest records.
I want to do the following algorithm
Take Joe's interest record 1 and look for matching hobbies and locations from the interest database. Put any matching interest id's in the matches field. Then go to joe's interest record 2 etc..
I guess what I need is some sort of for loop that will loop through all of joe's intersts and then do an update each time it finds a match in the interest database. Is that even possible in MySQL?
Further example:
I am Dan. I have 3 interests. Each interest is composed of 3 subjects:
Dan cats,nutrition,hair
Dan superlens,dna,microscopes
Dan film,slowmotion,fightscenes
Other people may have other interests
Joe:
Joe cats,nutrition,strength
Joe superlens,dna,microscopes
Moe
Moe mysql,queries,php
Moe film,specialfx,cameras
Moe superlens,dna,microscopes
Now I want the query to return the following when I log in as Dan:
Here are your interest matches:
--- is interested in cats nutrition hair
Joe is interested in cats and nutrition
Joe and Moe are interested in superlens, dna, microscopes
Moe is interested in film
The query needs to iterate through all Dan's interests, and compare 3,2,1 subject matches.
I could do this in php from a loop but it would be calling the database all the time to get the results. I was wondering if there's a crafty way to do it using a single query Or maybe 3 separate queries one looking for 3 matches, one for 2 and one for 1.
This is definitely possible with MySQL, but I think you may be going about it in an awkward way. I would begin by structuring the tables as follows:
TABLE Users ( userId, username, location )
TABLE Interests( interestId, hobby )
TABLE UserInterests( userId, interestId, level )
When a user adds an interest, if it hasn't been added before, you add it to the Interests table, and then add it to the UserInterests table. When you want to check for other nearby folks with similar interests, you can simply query the UserInterests table for other people who have similar interests, which has all that information for you already:
SELECT DISTINCT userId
FROM UserInterests
WHERE interestId IN (
SELECT interestId
FROM UserInterests
WHERE userId = $JoesID
)
This can probably be done in a more elegant fashion without subqueries, but it's what I thought of now.
As per special request from daniel, although it's kind of duplicate but never mind.
The schema explained
TABLE User (id, username, location )
TABLE Interests(id, hobby )
TABLE UserInterest(userId, interestId, level )
Table users has just user data and a primary key field at the start: id.
The primary key field is a pure link field, the other fields are info fields.
Table Interest again has a primary key that is use to link against and some info field
(ehm well just one, but that's because this is an example)
Note that users and interests are not linked in any way whatsoever.
That's odd, why is that?
Well there is a problem... One user can have multiple intrests and intrests can belong to multiple people.
We can solve this by changing to users table like so:
TABLE users (id, username, location, intrest1, intrest2, intrest3)
But this is a bad, really really bad idea, because:
This way only 3 interests per user are allowed
It's a waste of space if many users have 2, 1 or no interests
And most important, it makes queries difficult to write.
Example query for linking with the bad users table
SELECT * FROM user
INNER JOIN interests ON (user.intrest1 = interests.id) or
(user.intrest2 = interests.id) or
(user.intrest3 = interests.id);
And that's just for a simple query listing all users and their interests.
It quickly gets horribly complex as things progress.
many-to-many relationships
The solution to the problem of a many to many relationship is to use a link table.
This reduces the many-to-many relationship into two 1-to-many relationships.
A: 1 userinterest to many user's
B: 1 userinterest to many interests
Example query using a link-table
SELECT * FROM user
INNER JOIN userInterest ON (user.id = userInterest.userID) //many-to-1
INNER JOIN interest ON (interest.id = userInterest.InterestID); //many-to-1
Why is this better?
Unlimited number of interests per user and visa versa
No wasted space if a user has a boring life and few if any interests
Queries are simpler to maintain
Making it interesting
Just listing all users is not very fun, because then we still have to process the data in php or whatever. But there's no need to do that SQL is a query language after all so let's ask a question:
Give all users that share an interest with user Moe.
OK, lets make a cookbook and gather our ingredients. What do we need.
Well we have a user "Moe" and we have other user's, everybody but not "Moe".
And we have the interests shared between them.
And we'll need the link table userInterest as well because that's the way we link user and interests.
Let's first list all of Moe's Hobbies
SELECT i_Moe.hobby FROM interests AS i_Moe
INNER JOIN userInterests as ui2 ON (ui2.InterestID = i_Moe.id)
INNER JOIN user AS u_Moe ON (u_Moe.id = ui2.UserID)
WHERE u_Moe.username = 'Moe';
Now we combine the select for all users against only Moe's hobbies.
SELECT u_Others.username FROM interests AS i_Others
INNER JOIN userinterests AS ui1 ON (ui1.interestID = i_Others.id)
INNER JOIN user AS u_Others ON (ui1.user_id = u_Others.id)
/*up to this point this query is a list of all interests of all users*/
INNER JOIN Interests AS i_Moe ON (i_Moe.Hobby = i_Others.hobby)
/*Here we link Moe's hobbies to other people's hobbies*/
INNER JOIN userInterests as ui2 ON (ui2.InterestID = i_Moe.id)
INNER JOIN user AS u_Moe ON (u_Moe.id = ui2.UserID)
/*And using the link table we link Moe's hobbies to Moe*/
WHERE u_Moe.username = 'Moe'
/*We limited user-u_moe to only 'Moe'*/
AND u_Others.username <> 'Moe';
/*and the rest to everybody except 'Moe'*/
Because we are using INNER JOIN's on link fields only matches will be considered and non-matches will be thrown out.
If you read the query in english it goes like this.
Consider all users who are not Moe, call them U_others.
Consider user Moe, call him U_Moe.
Consider user Moe's Hobbies, call those i_Moe
Consider other users's Hobbies, call those i_Others
Now link i_Others hobbies to u_Moe's Hobbies
Return only users from U_Others that have a hobby that matches Moe's
Hope this helps.
I have a list of checkboxes in my form, user may chose any of them, or just all of them.
Think that user selects the type of sport he is interested.
I need the best database structure to store this user choise. So that, in future I can get all this data.
I think, I just can store each (userID, sport) choise as a new row in database table. But it is confusing me, because table will expand faster with just a few number of users.
Any ideas, brothers?
You can setup a many-to-many table such as:
FavoriteSports
------
id user_id sport_id
1 5 20
Where you have:
User
-------
id name
5 Mike
Sport
-----
id name
20 Football
This makes sense because a user has many sports, and a sport has many users.
Deciding how to do this is called normalizing.
There are multiple ways to do this depending on how normalized you want your data.
The simplest way is what you described.
userID userName sport
Or you can have 2 tables
users
userID userName sportID
sports
sportID sport
Or you can have 3 tables
users
userID sportName
sports
sportID sportName
user_sports
userID sportID
Where the user_sports table contains which user likes which sport.
Which method you chose depends on the relationships of your data and how much duplication you expect.
If you are only storing which sport a user has chosen, I would choose the second one. That prevents duplication of sport names but only allows one sport per user. If you want to allow users to choose multiple sports, use the third option.