473,387 Members | 1,303 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Storing list data in MySQL

How would a set of related values be stored together in a MySQL db?

For example, if I wanted to store a user's buddy list, then the way I can think of would be something like this:

user | friend
John | Jim
John | Bob
John | Amy
Bob | Jim
Bob | Amy

So John's friendlist would include Jim, Bob, and Amy, and Bob's friendlist would include Jim and Amy. But it seems really inefficient to create a new row every time a new entry in the list is needed

I want to be able to store values like this:

user | buddylist
John | Jim,Bob,Amy
Bob | Jim,Amy

What would be the most efficient way to do this?
Sep 13 '08 #1
9 34451
Atli
5,058 Expert 4TB
Hi.

The second method you mentioned should never be used. No field should ever contain more than a single piece of data.

A simple method to do something like that would be to create two tables. One for the user info and a second for the relationship between each user.

It might look something like:
Expand|Select|Wrap|Line Numbers
  1. User
  2. ----------------
  3. UserID UserName
  4. 1        John
  5. 2        Jim
  6. 3        Amy
  7. ----------------
  8.  
  9. UserRelation
  10. ----------------
  11. UserID FriendID
  12. 1        2
  13. 1        3
  14. 2        1
  15. 3        2
  16. ----------------
  17.  
Where both the fields of the UserRelation talble reference the UserID field in the User table. You could even join them as the Primary Key to avoid duplicate entries.
Sep 13 '08 #2
Hi.

The second method you mentioned should never be used. No field should ever contain more than a single piece of data.

A simple method to do something like that would be to create two tables. One for the user info and a second for the relationship between each user.

It might look something like:
Expand|Select|Wrap|Line Numbers
  1. User
  2. ----------------
  3. UserID UserName
  4. 1        John
  5. 2        Jim
  6. 3        Amy
  7. ----------------
  8.  
  9. UserRelation
  10. ----------------
  11. UserID FriendID
  12. 1        2
  13. 1        3
  14. 2        1
  15. 3        2
  16. ----------------
  17.  
Where both the fields of the UserRelation talble reference the UserID field in the User table. You could even join them as the Primary Key to avoid duplicate entries.
This is pretty much the setup I currently have, but I thought it was inefficient. So just for clarification, this is the best way to store a list-type data set? If I wanted to store, say, a list of items that the user owned, it'd be the same thing? A table with itemID/itemName and another with userID/itemOwned?

One other thing. On that second table, what would the unique primary key be? Would I just have an arbitrary one such as entryID that would serve no purpose? Because tools like MySQL Query Browser require a primary key to be able to manipulate a table.
Sep 14 '08 #3
Atli
5,058 Expert 4TB
Yes. This is pretty much the basis of a N:M relationship.

This is also far more efficient that what you were suggesting in your first post.

Firstly, your first example stored everything as text fields. It is much faster to search through integers than text, even if the text fields are indexed. Not to mention the amount of disk space all that text takes, compared to the integers.

You second example, while using a less complex table structure, stores multiple pieces of data in each field as a string, which has to be processed and split into each individual part every time any one of them needs to be used.
The overhead of that is far beyond any overhead a simple JOIN would cause, especially using a simple structure, like the one I posted.

The second table doesn't need the traditional one-column integer primary key we use on most tables.
You can use the two foreign key columns as the primary key:
Expand|Select|Wrap|Line Numbers
  1. CREATE TABLE UserRelation (
  2.   UserID_FK INT Unsigned Not Null References User(UserID),
  3.   FriendID_FK Int Unsigned Not Null References User(UserID),
  4.   Primary Key (UserID_FK, FriendID_FK)
  5. );
  6.  
This will also protect the table from duplicate entries, like linking one user twice to the same friend.
Sep 14 '08 #4
Yes. This is pretty much the basis of a N:M relationship.

This is also far more efficient that what you were suggesting in your first post.

Firstly, your first example stored everything as text fields. It is much faster to search through integers than text, even if the text fields are indexed. Not to mention the amount of disk space all that text takes, compared to the integers.

You second example, while using a less complex table structure, stores multiple pieces of data in each field as a string, which has to be processed and split into each individual part every time any one of them needs to be used.
The overhead of that is far beyond any overhead a simple JOIN would cause, especially using a simple structure, like the one I posted.

The second table doesn't need the traditional one-column integer primary key we use on most tables.
You can use the two foreign key columns as the primary key:
Expand|Select|Wrap|Line Numbers
  1. CREATE TABLE UserRelation (
  2.   UserID_FK INT Unsigned Not Null References User(UserID),
  3.   FriendID_FK Int Unsigned Not Null References User(UserID),
  4.   Primary Key (UserID_FK, FriendID_FK)
  5. );
  6.  
This will also protect the table from duplicate entries, like linking one user twice to the same friend.
I'm not familiar with the syntax for creating a table which references foreign keys. Could you explain the use of two column names with Primary Key()? I've only seen Primary Key (x), not Primary Key (x, x).

Thanks for the help.
Sep 14 '08 #5
Atli
5,058 Expert 4TB
Sure.

Simply put, if you specify multiple columns in the Primary Key clause, MySQL will create a joint key, including all of them.

The actual value of the Primary Key would be something like:
Expand|Select|Wrap|Line Numbers
  1. col1-col2-col3-colN
Where the col1-colN values would be replaced by the value of each column in the given row.

Because of this, you can not create a row containing the exact combination of values for the PK columns as any previous row. The Primary Key value must be unique, even tho each of the columns that make up the Primary Key can have duplicate entries.

Which makes this ideal for the exact situation we were discussing.
Sep 14 '08 #6
So if the User and UserRelation tables were implemented in an actual application, in order to display John's buddylist, you'd have to do the following:

Expand|Select|Wrap|Line Numbers
  1. SELECT UserID FROM `User` WHERE UserName = 'John'
And we'd get 1. Then we'd do...
Expand|Select|Wrap|Line Numbers
  1. SELECT FriendID FROM `UserRelation` WHERE UserID = 1
And we'd get 2 and 3. Then we'd do...
Expand|Select|Wrap|Line Numbers
  1. SELECT UserName FROM `UserRelation` WHERE UserID = 2
  2. SELECT UserName FROM `UserRelation` WHERE UserID = 3
And we'd finally get John's buddylist, Jim and Amy. Is all of this really faster than just having:
Expand|Select|Wrap|Line Numbers
  1. Friend
  2. ----------------
  3. UserName FriendName
  4. John     Jim
  5. John     Amy
  6. Jim      John
  7. Amy      John
  8. ----------------
  9.  
Where we could simply run SELECT FriendName FROM `Friend` WHERE UserName = 'John'?
Oct 11 '08 #7
Atli
5,058 Expert 4TB
Yes. Matching text is usually a lot slower than matching numbers, although your approach is a very simplistic one.
Not to mention that the way you are suggesting would waste infinitely more disk-space than the proper way.

You need to use the tools available in a relational database.
A SELECT query is not just limited to the SELECT FROM WHERE syntax. You can have it fetch data from more than one table, and have it filter this data based on more then a simple boolean x = y check.

This is how such a database should be used:
Expand|Select|Wrap|Line Numbers
  1. SELECT `User`.`UserName` AS 'Friend Name' 
  2. FROM `User`
  3. INNER JOIN `UserRelation`
  4.     ON `User`.`UserID` = `UserRelation`.`FriendID_FK`
  5.     AND `UserRelation`.`UserID_FK` = (
  6.         SELECT `UserID` FROM `User`
  7.         WHERE `UserName` = 'John'
  8.     )
  9.  
It Joins the two tables and filters the data to show the friends of the user selected by the subquery.
Note that I assume that the UserName is unique, which is why I use it in the subquery without a LIMIT clause.

It does exactly what all of your SELECT queries do, but in the proper way.
This is the true power of a relational database, it's ability to join tables and filter the data based on more than just a single table SELECT FROM WHERE statement.

If you don't get the syntax, I suggest you read about Join and Subquery syntax.
If it's all new to you, you may want to look up some tutorials on those concepts.
Oct 11 '08 #8
This is all fine and good until the friend has more than one friend lol
Mar 17 '11 #9
Atli
5,058 Expert 4TB
@NetDynamic
How do you mean? The example tables I posted in post #2 show John being friends with both Amy and Jim.

The whole purpose of the concepts we are talking about here is to link one row to multiple other rows. (Read: to allow one person to be friends with multiple persons.)
Mar 20 '11 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

8
by: Steven | last post by:
Hi there, I am wanting to store price data as n.nn format, so if the user enters "1" the data that gets stored is "1.00" Is there a way to do this. Cheers Steven
3
by: dave | last post by:
Hello there, I am at my wit's end ! I have used the following script succesfully to upload an image to my web space. But what I really want to be able to do is to update an existing record in a...
0
by: John Hicks | last post by:
Is there an accepted best practice on whether to store decimal currency amounts (e.g. dollars and cents) in MySQL decimal column types? Certainly, the most straightforward way is to use decimal...
0
by: Eben Goodman | last post by:
I am storing book isbn numbers in a table. isbn numbers are 10 digit numbers and many start with 0. The data type of the field I am storing this info in is a bigint(16) unsigned. It appears that...
8
by: Francesco Moi | last post by:
Hello. I'm parsing an XML file, and trying to store its contents into a MySQL database. But I've got problems. If I print the word before storing it, I get 'música' (OK). But if I store it...
1
by: Kay | last post by:
A linked list is storing several names. I want to make a queue if I input a name that is same as the linked list. How to make each node of a linked list storing a queue that are different with each...
6
by: Kyle Teague | last post by:
What would give better performance, serializing a multidimensional array and storing it in a single entry in a table or storing each element of the array in a separate table and associating the...
1
by: tomi.trescak | last post by:
Hi I have a problem with storing rich text in MySQL. I store rich text in MySQL (in column with type "text") which i get from Rich Textbox control. When i do reverse processing by trying to...
2
by: assgar | last post by:
Hi Developemnt on win2003 server. Final server will be linux Apache,Mysql and PHP is being used. I use 2 scripts(form and process). The form displays multiple dynamic rows with chechboxs,...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.