a user bookmark system database design - database

my user need to bookmark the articles, videos, pictures posted by the others.
now I have a user table, an article table, a video table.
and I come up with two way to store the bookmark data..
first, I can create three one-to-many table.
the second way is only create a table and add a category column on it..
with the first approach, I can store foreign keys to associate with the articles and video table. witch is easier for the orm system
and the second way only need a table, but can't store the relationship..
so. which one should I choose,or Is better???
the third way is something like.

I have worked with tables that employ both types of relationships. For ease of use, I do not prefer the second method. There is another method you may wish to try, which would be (sorry, no picture):
USER
UserId
USER_BOOKMARK
UserBookmarkId
UserId
BookmarkAssetId
USER_BOOKMARK_ASSET
UserBookmarkAssetId
UserBookmarkId
AssetType (Title, href, image, caption, tooltip, etc)
AssetStringValue (nullable)
AssetNumberValue(nullable)
AssetByteArray (nullable)
You would get a bookmark like:
SELECT * AS UserBookmarkLinks
FROM USER_BOOKMARKS ub
INNER JOIN USER_BOOKMARK_ASSETS uba
ON ub.UserBookmarkId = uba.UserBookmarkId
WHERE ub.UserId = 12345
AND uba.AssetType = "Link"
From there you may have BOOKMARK_TYPE_ASSETS which tells you what assets are included with each type and which field in USER_BOOKMARK_ASSETS it uses. This is a little more involved with tables, but a lot closer to normalized.

Related

Normalizing a database with user, a date, and check-ins

I'm designing a database and I'm looking for the best way to format the tables. The users can check in and check out boxes, tapes, CDs, and other types of media. I want a history of who has checked out what and at what times. Here is a simplified version of my current schema:
User(id, first_name, last_name)
Box(id, description)
Tape(id, description)
CD(id, title)
check_in(id, in_date, out_date, fk_user)
check_in_history(id, fk_checkin, media_type)
I have a table for the User and the different types of media. The check-ins are also stored in a separate table. For the check-in history I have the foreign key of the check-in table along with a field for the media type so I can determine which table, and thus which type of media is being referred to by the check-in. Still, this seems like a kludge and feels inefficient. Is there a better way to design this database?
Edit: The different types of media have a lot of different properties that I left out for simplicity so they can't be in the same table.
I would do it this way; Have one table for media with id,type,description, title.
The check_in table needs to have a link to the media table. Thus the check_in links the user and the media.
There is no reason for a history table. The check_in table will have a history of all loans.

Getting records structured the same way only partially

While surfing through 9gag.com, an idea (problem) came up to my mind. Let's say that I want to create a website where users can add diffirent kinds of entries. Now each entry is diffirent type and needs diffirent / additional columns.
Let's say that we can add:
a youtube video
a cite which requires the cite's author name and last name
a flash game which requires additional game category, description, genre etc.
an image which requires the link
Now all the above are all entries and have some columns in common (like id, add_date, adding_user_id, etc...) and some diffirent / additional (for example: only flash game needs description or only image needs plus_18 column to be specified). The question is how should I organize DB / code for controlling all of the above as entries together? I might want to order them, or search entries by add_date etc...
The ideas that came up to my mind:
Add a "type" column which specifies what entry it is and add all the possible columns where NULL is allowed for not related to this particular type columns. But this is mega nasty. There is no data integration.
Add some column with serialized data for the additional data but it makes any filtration a total hell.
Create a master (parent) table for an entry and separate tables for concrete entry types (their additional columns / info). But here I don't even know how I'm supposed to select data properly and is just nasty as well.
So what's the best way to solve this problem?
The parent table seems like the best option.
// This is the parent table
Entry
ID PK
Common fields
Video
ID PK
EntryID FK
Unique fields
Game
ID PK
EntryID FK
Unique fields
...
What the queries will look like will largely depend on the type of query. To, for example, get all games ordered by a certain date, the query will look something like:
SELECT *
FROM Game
JOIN Entry ON Game.EntryID = Entry.ID
ORDER BY Entry.AddDate
To get all content ordered by date, will be somewhat messy. For example:
SELECT *
FROM Entry
LEFT JOIN Game ON Game.EntryID = Entry.ID
LEFT JOIN Video ON Video.EntryID = Entry.ID
...
ORDER BY Entry.AddDate
If you want to run queries like the one above, I suggest you give unique names to your primary key fields (i.e. VideoID and GameID) so you can easily identify which type of entry you're dealing with (by checking GameID IS NOT NULL for example).
Or you could add a Type field in Entry.

Database Design for Facebook "likes"

New to database design and I was wondering how to efficiently design something like Facebook likes with future scalability in mind.
Let's say you have 3 tables: users, photos and albums.
Let's say a user can like either a photo or an album.
Should I use 1 table for both types of likes?
This would probably mean it would have an user_id, like_type(0-photo, 1-album etc), like_value(the id value of whatever content it is, whether it is photo_id or album_id)?
or have 2 different tables for each likes (ex. photos_likes and albums_likes)?
which would only contain user_id and photo/album_id
I want to make sure that the database design is clean and semi-scaleproof whether we add many more objects in the future(videos, comments, notes, etc) or have a ton of likes.
Thanks!
You could try a inherited table approach see implementing table inheritence for more indepth detail.
But essentially it works just like inheritence in code, you have a base table 'Like' and then tables which 'inherit' from it 'CommentLike', 'PhotoLike' etc.
See attached diagram for a quick mockup.
Two different tables. This way if you ever have an object that you want to add likes to later you can just make a new table "object_likes" and store the likes there.
If you wanted to store them all in one table, you would need a type table, which would store all the types of objects, and in your like table you would have to reference the type_id. This would let you add types later.
To me the first method is much better.

Database Normalization and Nested Lists -- Cannot Think of a Solution

I am trying to implement a system on my website similar to that of Facebook's "Like" feature. Where users can click a button which counter++'s. However, I have run into a problem in terms of efficiently storing data into my DB.
Each story has it's own row in the stories table in my DB with the columns like and users_like.
I want each person to only be able to like the story once. Therefore I need to somehow store data that shows that the user has, in fact, like++'d the post.
All I could thing of was to have a column named users_like and then add each user, followed by a comma, to the column using CONCAT and then using the php function to explode the data.
However, this method, as far as I know, is in the opposite direction of database normalization.
What is the best way to do this and I understand "best" is subjective.
I cannot add a liked flag to the user table because there will be a vast number of stories the person could 'like.'
Thanks
You need a many to many table in your database that will store a foreign key to the stories table and a foreign key to the user table. You put a constraint on this table saying that the story fk - user fk combo must be unique.
You now don't even have to have a like column, you just count the number of rows in the many to many table corresponding to your story.

What is the best way of storing a geographical information in a relation db?

I want to save a geographical data in a relational db and be able to query for data based on their location (country, state or similar not coordinates).
My current solution is to have 4 extra fields (all countries I'm interested in have 2 or 3 administrative divisions) in my table and filter on strings. But I realize that this is a bad solution and would like to normalize my table.
I will also use that data to determine which page my users wants to visit, so it must be simple to lookup a request like "/usa/california/san_fransisco/..."
The only other solution I can come up with is to store those 4 extra fields in another table and link them with a foreign key but that would still mean some data duplication as country name would duplicated in allot of rows.
Is there any better way of doing this?
Normalizing is definitely the way to go. Databases are designed to function that way. Yes the query might look long but it's not that bad. It might look something like this:
select * --or whatever fields you need
from Customer
left outer join City on (Customers.CityID = City.CityID)
left outer join State on (City.StateID = State.StateID)
left outer join Country on (State.CountryID = Country.CountryID)
where CustomerID = 1234
You're on the right track with putting the info in tables. Their called lookup tables. If you want to go the full relational route, you can have the entity link with a foreign key to the city lookup table. The city table links to the state table. The state table links to the country table. You could also store a text version of the complete location in the entity's original table for data display.
My current solution is to have 4 extra fields (all countries I'm interested in have 2 or 3 administrative divisions) in my table and filter on strings. But I realize that this is a bad solution and would like to normalize my table.
I don't think that this is a bad solution. Storing simple geographical/address-based information per row and using WHERE to fetch all records that match is fairly standard procedure. Using a foreign key to link to a separate table is going to be additional work and won't be any faster.
The searching/request using a RESTful interface (as you suggested) is a good idea, however.
Go the normalized route. Joining tables is NOT slow, or complicated. PK of each table will be an integer with a clustered index. Foreign keys will have an index. The join is going to fly.
If you want to list cities in a drop down list, you don't want duplicates. You may list all the cities under a state. De-normalized will slow your query with "distinct", i guarantee you that is slower going the de-normalized route. ironic?
But there is a case for de-normalized. There are millions of addresses. It will probably not be feasible to enter all addresses in your application. So you are going to rely on..... free text input from the user. In this case you don't care about exact correctness or duplicates, you are forced to just accept whatever is data is thrown at you due to the impossibility of having exhaustive data to validate against. And you would rather not bother inserting to "lookup" tables as you don't trust the input to begin with.
You could go for a re-cursive model if you want ultra flexibility to handle different countries. Some countries may not have states, counties, etc. They all have their own hierarchy.

Resources