store list of IDs mysql - mysql

I want to store a list of book IDs for a wishlist in mysql; here's what the relevant tables look like:
User_Wishlists
user_id, list_title, list_id (PK)
Wishlist
list_id (FK), book_id (PK)
The issue is with the book_ID. Most users will have multiple books on their lists, but it seems strange to have that represented by book1_id, book2_id, etc. in the table. Is there a better way to store a list of these book_IDs in mysql? I need to be able to retrieve and display a user's wishlist for them.

You need to have an association table that joins users to wishlists. Remember the zero, one, or N principle of database design. Either you have no relationship, a one to one, or a one to many. Using things like book1_id is almost always a defective design.
You may find this is a better structure:
Wishlist
wishlist_id, user_id, ...
WishlistEntry
wishlist_id, book_id, ...
Associate the wishlist with the user directly, then use the WishlistEnry table to find which books are on which wishlist.

Related

Design database for category, subcategory and associated books

I know there has been a few answer to a couple of questions similar to the one am asking. But their approach didn't look convincing.
My question is how would I structure a database for a category that can have books and a subcategory which can also have books?
I have already design a database, but am not convinced by the approach. So I would really appreciate if the guys with experience gave me some advice or improvement or a completely different approach.
This how my tables look like (bare in mind this is not the actual code)
TABLE Category
ID
user_id -- Foreign key from user
name
TABLE SubCategory
ID
user_id
category_id
name
The table for the book have the same design.
There's no reason to have more than one table for "categories", whether it be a top-level category or a sub-category. They're all just "categories".
So, have a single table called "categories", with a parent_id field:
// categories table
id
name
user_id
parent_id
When you want to pull all top level categories, just run your query against the categories table with a condition that parent_id is null.
Then, when you want to pull sub categories, just run the query against the categories table with a condition that parent_id = 123 (or whatever).
Not only does this keep everything a lot cleaner, but it also allows for expansion in case you want to continue adding sub-sub-sub-sub categories...etc.
Another option is to use CakePHP's TreeBehavior.
I personally just rather use the way I suggested above, but might just be because I haven't taken the time to really understand this behavior enough.
If parent_category is null then it is a top level. If it is non-null then it is a sub category.
TABLE Category
ID
name
parent_category

Mysql: is it better to split tables if possible?

To make you understand my question I'll give you an example:
I have a chat web app with many rooms, let's say 5 rooms.
People can choose to stay only in one room and they choose it at login.
When they choose the room I have to retrieve the people already in the room, so I can structure my db in two ways:
each room one table with the people being records;
all the rooms in one table, people are the records and a column indicating the room they are in;
In the first case the query would be:
SELECT * FROM 'room_2' WHERE 1
In the second case the query would be:
SELECT * FROM 'rooms' WHERE room = 'room_2'
Which is the best?
I think the only parameter to consider is performance, right?
In this example, no, because people are all 'like' objects and should therefore be in the same table.
All people and rooms in one table with a primary key on people, in this simple example.
Table Rooms(pk_person, personName, table_id)
But I want to talk about a structure that you will want to consider as your website grows. You’ll want three tables, one for each object (chat rooms, people) and one for the relationships.
Chat_Rooms(pk_ChatId, ChatName, MaxOccupants, other unique attributes of a chat room)
People(pk_PersonID, FirstName, LastName, other unique attributes of a person)
Room_People_Join(pk_JoinId, fk_ChatId, fk_PersonID, EnterDateTime, ExitDateTime)
This is a “highly normalized” structure. Each table is a collection of like objects, the join allows for many to many relationships, and object rows are not duplicated. So, a Person with all their attributes (name, gender, age) is never duplicated in the person table. Also, the person table never defines which chat rooms a person is in, because a person could be in one, many, none, or may have entered and exit multiple times. The same concept applies to a chat room. A chat rooms features, such as background color, max occupants, etc. have nothing to do with people.
The Room_People_Join is the important one. This has a unique primary key for which chat rooms a person is in and when they were there. This table grows indefinitely, but it tracks usage. Including the relationship table is what logically normalizes your database.
So how do you know which users are currently in chat room 1? You join your people and rooms to the join table with their respective Primary and Foreign keys in your FROM clause, ask for the columns you want in your SELECT clause, and filter for chat room 1 and people who haven’t yet left.
SELECT p.FirstName, p.LastName, r.ChatName
FROM Room_People_Join j
JOIN People p ON j.fk_PersonID = p.pk_PersonID
JOIN Chat_Rooms r ON j.fk_ChatId = r.pk_ChatId
WHERE r.ExitDateTime IS NOT NULL
AND pk_ChatId = 1
Sorry that’s long winded, but I extrapolated your question for database growth.
The answer is very simple and strongly recommended - one database table for all rooms for sure! What if you will later like to create rooms dynamically!? For sure you would not create new tables dynamically.

Mysql setup for multiple users with large number of individual options

i'm building a study tool and i'm not sure of the best way to go about structuring my database.
Basically, i have a simple but big table with around 50000 bits of information in it.
info (50'000 rows)
id
info_text
user
id
name
email
password
etc
What i want is for the students to be able to marked each item as studied or to be studied(basically on and off), so that they can tick off each item when they have revised it.
I want to build tool to cope with thousands of users and was wondering what the most efficient/easiest option way of setting up the database and associated queries.
At the moment i would lean towards just having one huge table with two primary keys one with user id and then id of the info they had studied and then doing some sort of JOIN statement so i could only pull back the items that they had left to study.
user_info
user_id
info_id
Thanks in advance
Here is one way to model this situation:
The table in the middle has a composite primary key on USER_ID and ITEM_ID, so a combination of the two must be unique, even though individually they don't have to be.
A user (with given USER_ID) has studied a particular item (with given ITEM_ID) only if there is a corresponding row in the STUDIED table (with these same USER_ID and ITEM_ID values).
Conversely, the user has not studied the item, if and only if the corresponding row in STUDIED is missing. To pull all items a given user hasn't studied, you can do something like this:
SELECT * FROM ITEM
WHERE NOT EXISTS (
SELECT * FROM STUDIED
WHERE
USER_ID = <given_user_id>
AND ITEM.ITEM_ID = STUDIED.ITEM_ID
)
Or, alternatively:
SELECT ITEM.*
FROM ITEM LEFT JOIN STUDIED ON ITEM.ITEM_ID = STUDIED.ITEM_ID
WHERE USER_ID = <given_user_id> AND STUDIED.ITEM_ID IS NULL
The good thing about this design is that you don't need to care about STUDIED table in advance. When adding a new user or item, just leave the STUDIED alone - you'll gradually fill it later as users progress with their studies.
I would do something like this:
1) A users table with a uid primary key
2) A enrolled table (this table shows all courses that have enrolled students) with a primary key of (uid, cid)
3) A items (info) table holding all items to study, with a primary key of itemid
Then in the enrolled table just have one attribute (a binary flag) 1 means it has been studyed and 0 means they still need to study it.

'Likes' system database

I am developing web application where I have to implement 'Likes' system as facebook has. Application will have a few categories of products that customer can 'like'. So I have started to create database, but I stuck on one obstacle. As I understand there are two ways of doing this:
First. Create one database table with fields of "id, user_id, item_category, item_id". When user click 'like' button information will be saved in this table with various categories of products (item_category).
Second. Create several tables for certain categories of item. For instance, "tbl_item_category_1, tbl_item_category_2, tbl_item_category_3" with fields of "user_id, item_id".
Would be great to get more insight about best practices of this kind database structures. Which works faster? and more logical/practical? I will use only several categories of items.
I would go with the first version with a table structure similar to this:
User Table: PK id
id
username
Category Table: PK id
id
categoryname
Like Table: PK both user_id and catgory_id
user_id
category_id
Here is a SQL Fiddle with demo of table structure with two sample queries to give the Total Likes by user and Total Likes by category
The second one - creating multiple tables is a terrible idea. If you have 50-100 categories trying to query those tables would be horrible. It would become completely unmanageable.
If you have multiple tables trying to get a the total likes would be:
Select count(*)
from category_1
JOIN category_2
ON userid = userid
join category_3
ON userid = userid
join .....
Use one table, no question.
The first method is the correct one. Never make multiple tables for item categories, it makes maintaining your code a nightmare, and makes queries ugly.
In fact, the general rule is that anything that is dynamic (i.e. it changes) should not be stored as a set of static objects (e.g. tables). If you think you might add a new type of 'something' later on, then you need a 'something' types table.
For example, imagine trying to get a count of how many items a user has liked. With the first method, you can just do SELECT COUNT(*) FROM likes WHERE user_id = 123, but in the second method you'd need to do a JOIN or UNION, which is bad for performance and bad for maintainability.
The first method is the correct one. Because you dont know how many categories you will be having and it is very difficult to get the data.

MySQL relationships: Bid with products and users

I have a simple site where users can bid on a product. The model looks like this:
Obviously different users can bid, so how do I draw the missing link to the 'users' table?
I'm a little confused whether to use identifying or non-identifying relationship.
Updated:
You say: "... users can bid on a product."
This suggests that there is a relationship (Bids) between Users and Products. You could name it user_bids_on_product or just bid.
I would remove the relationship between user and product (unless it means something else like the owner of a product) and unify your bids and bids_has_product into one table:
user_bids_on_product
--------------------
product_id FK to product
user_id FK to user
price
The (product_id, user_id) should not be the Primary Key for this table, as we assume a user can bid multiple times on a product.
You could add a surrogate id and make that the PK or add a bid_number column and make the compound (product_id, user_id, bid_number) the PK. You could alternatively make the (product_id, bid_number) the PK (the bid_number could mark the order of the bids per product, like an auction in this case). I think that's up to you to decide.
Identifying relationships:
Non-identifying relationships:
A User can make one Bid on a Product; a User can Bid on more than one Product; a Product can have more than one Bid; a Bid is associated with only a single Product.
I think you need to have a relationship between a User and the Bids they make. It's one-to-many.
Another question regarding your updated diagram: would a User assign a Rating to a Product, in much the same way they give a Bid? Is that worth tracking? If yes, I'd have a relationship between User and Rating.
A simple identifying relationship b/w users and bids makes sense, bids can't exist without a user.
Its a simple one to many relations, as users "has_many" bids.