views:

54

answers:

3

So I'm making a website that allows users to build contact lists. So their are users, the users have lists, and the lists have contacts. It seems to me that I need 3 tables for this but I just want to make sure.

There would be a User table of course, and then a "List of Lists" table that has the username, and listname, as primary key along with whatever other info we want to attach to the lists as a whole. Finally, for lack of a better word, the List table which would again have the username/listname p.k., then the contact ID and notes and such that the user attaches to that contact on that specific list.

I hope that is a clear explanation. For some reason I feel unsure about this arrangement. For one thing if the website becomes popular the List table could swell to billions of rows. And it also feels a little weird that everybody's list info is all jumbled up in the same table. I suppose I could create separate tables for each user and even for each list but that seems like a bad idea for other reasons.

My db explanation assumes I can use foreign keys on my tables which at the moment isn't actually an option. If I can't get InnoDB tables enabled I will probably use ID's for the lists instead of depending on a compound key. Maybe I should do this anyway?

+2  A: 

You do not want to create a table per user. It will be your worst nightmare further down the road. I would have gone for something like this:

User Table
----------
User_ID - Integer - Indexed
Username - VarChar[8]
First_Name - VarChar[30]
Last_Name - VarChar[40]

List Table
-----------
List_ID - Integer - Indexed
User_ID - Integer - Indexed
List_Name - VarChar[30]

List_Contact Table
--------------
List_ID - Integer - Indexed
Contact_ID - [whatever data type it is in the existing Contact table]

User.User_ID=List.User_ID
List.List_ID=List_Contact.List_ID
List_Contact.Contact_ID=Contact.Contact_ID [Linking to the existing Contact table]

If you build in some caching of the record sets, you won't have much of a performance issue even if you got tons of records in the database. After all, all users won't be on the system at once.

Edit: Changed the design to fit the existing Contact table.

Gert G
Why do you have first_name, last_name in the contact table as well... isn't that redundant?
Mark
I assumed that a contact has a first and last name. Or are the contacts other users in the system? Then the Contact table shouldn't have First_Name, Last_Name or Phone, but a field named Contact_User_ID (Just to not confuse it with the User_ID of the person he's a the contact for). Notes and stuff would go in the Contact table, but all person meta data (it already have First_Name, Last_Name, but you would add on for instance Phone, Address etc) would go in the User table.
Gert G
Thanks for the thorough diagram. One thing I should have explained better is that the contact lists are built out of and would reference an existing Contacts table. Not stuff the users make up and not other users in the User table.
Moss
That kills off the contact information. :) See above.
Gert G
OK, now I guess yours is the best answer. So you would definitely recommend having a list_ID rather than a compound key of user_ID and list_name? Because if lists are just names (ie. don't have any other metadata attached to them) then I could theoretically make due with just User, List and Contact tables.
Moss
Yes, because with an Integer/VarChar compound key you would degrade database performance, since the database will always be faster on finding numeric values than strings.
Gert G
A: 

That's one way of doing it. You could also have users add contacts and then add tags to their contacts.

Here's what I propose:

User
id
other fields

Contact
id
fk = User.id
tags
notes
other fields

You definitely don't want to start creating new tables for each user, then you'll have thousands/millions of tables and I don't think any DB is designed to be used like that. I'd recommend you get someone who knows more about DB design on your team.

Seán Hayes
So for your example instead of lists you would have tags, which are practically the same thing but you have eliminated one of the tables. So in order to display all the lists or tags that a user has you could query like: `SELECT DISTINCT tags FROM Contacts WHERE user_id = [whoever]`?I think the list concept is more appropriate in this case so probably the three table solution will provide the least headaches down the road. I think my DB knowledge is OK. I didn't actually want to make a million tables but I have had other developers in the past recommend such a thing with a straight face.
Moss
Yup, that query should work.Well, I'm glad you've decided not to use that strategy.
Seán Hayes
+1  A: 
Users(id, username, first_name, last_name)
FriendLists(id, user_id, name)
ListItems(id, list_id, user_id)

Your user table should hold all the basic data about your user. Nothing special here.

Then you have a friend list which consists of an id, a user_id (the list owner), and the name of the list ("best friends", "family", "people i hate").

And then you have your list items, which again have an id (everything should have an id, it just makes it easier to reference), a list id (which is a foreign key to the friend list, which in turn gives you owner), and then the user_id, which is the friend.

So, if Bob is Best Friends with Sally and Joe, then you would have

Users: (0, bob, Bob, Bobberson), (1, sally, Sally, Sallerson), (2, joe, Joe, Joeman)
FriendLists: (0, 0 (bob), "Best Friends")
ListItems (0, 0 (best friends list), 1 (sally)), (0, 0, 2 (joe))
Mark
Your solution seems closest to my needs. It sound like the general consensus is that my initial idea is correct. Now I'm just not sure about the ID's / foreign keys. Isn't it nicer to avoid integer IDs if there is already a unique field in the table? For example if all users on the website need a unique username why create an additional ID for them? The only reason I can think of is if you want to allow them to change their username, or list name as another example. Then you will have to update all fk references, which some databases can do automatically for you...
Moss
@Moss: Well, (1) yes, you may want to allow users to change their username in the future. (2) I *think* it's also easier on the DB to sort by integers than by strings. (3) Consistency. If every table has an `ID` field, you always know what the PK will be. (4) Should be more disk space efficient too. An `int` is smaller than a string.
Mark
Good points. I already incorporated a user management system that somebody else built which uses the username as a PK though so I think I will leave that one, or maybe I should find a more pro user system.
Moss