So I'm new to databases in the scope of the subject and looking for some advice for what I am sure is fairly simple. first I'm using MySql as my db I currently have two tables one for storing user accounts and details :
TABLE user
id | username | password | email_address | user_devices | contact_method
and another for storing video content by producers which looks like:
TABLE series
id | series_title | still_broadcasting | last_updated |
I would like to implement a feature where Users can select series which they wish to be notified of when new releases are made available and also select how to be notified about these releases (email or push notification ) and how often to be notified (on arrival, hourly, daily, weekly ) I am wondering whats the best way to go about doing this?
I've thought of these ideas by myself but am looking for a second opinion/ better way altogether: (all ideas minus 4 involve storing how to notify user along with how often in user table)
adding a text column to user table called following and just having csv's for each series
adding multiple boolean column's to user table one for each series
adding text column to series table with csv's of user's Id numbers following series
creating an entirely new table for notifications though i don't really see the purpose of this as its very redundant
I then plan to just add cron jobs to my server to actually go about regulaurly sending notifications to user's
Thanks in advance for any help.
First of all, it might be worth giving some articles on basic database design a read. A quick google turned up this which covers identifying relationships
http://www.datanamic.com/support/lt-dez005-introduction-db-modeling.html
Your best bet is to use a linking table i.e.
CREATE TABLE userHasSeries (
userID INT,
seriesID INT
);
This can then be used in an INNER JOIN query to get the users choices. What you are doing here is an n:m link between 2 tables. An example inner join would be
SELECT
u.id AS userID,
u.username,
s.seriesID,
s.series_title,
s.still_broadcasting,
s.last_updated
FROM users AS u
INNER JOIN userHasSeries AS uhs
ON uhs.userID = u.id
INNER JOIN series AS s
ON s.id = uhs.seriesID
If users.user_devices is also a comma seperated list I would advise heavily that you adopt a similar n:m approach there also.
A partial answer which complements what has been written in other answers:
Don't keep a list of devices in the 'user_devices' field - break this out into a separate table. In fact, you'll need two tables: one to list the various devices, and one a join table which has two fields: user_id and device_id. This will enable you to track which user has which device, but also to provide a list of users per device.
If I were you I would add a third table as following:
TABLE user
id | username | password | email_address | user_devices | contact_method |notification_type
TABLE series
id | series_title | still_broadcasting | last_updated
TABLE followings
id | user_id | series_id
In notification_type I would put (on arrival, hourly, daily, or weekly), now in the followings tables I will store all the user's preferred series.
Doing this way makes easy to add, delete, update, or select all user's preferred series. All will be simple SQL queries. Also you avoid parsing comma separated strings.
for example, if you want to get all preferred series of an user:
SELECT * FROM followings AS f INNER JOIN series AS s ON f.series_id = s.id WHERE f.user_id = ?
if want to get all users that prefer a serie:
SELECT * FROM followings AS f INNER JOIN user AS u ON f.user_id = u.id WHERE f.series_id = ?
Related
I have read various topics regarding table relations and while i am building my database i am a bit confused on what should i do.
I have 3 type of registration on my site(artist, fan, companies). Each registered user gets a unique key and username and the appropriate type of user (ex. fan). I am trying to involve music genres to all types of registration but genres will also be added to uploaded music files. At the moment i am storing one music genre per track and user by an array list that is shown in a form. Then system is storing it to the appropriate field. But i want some users to have more than 1 genres stored.
Now what i have done is below:
Users table (total 14 columns)
ID | username | email | password | type | signup | lastlogin | etc.
Settings table (total 10 columns)
ID | username | description | banner | country | genres | avatar etc.
Music table
ID | username | artist | title | maingenre | othergenre | cover | fileurl
By having in mind performance and let's assume that thousand of thousand users is registering...
Should i just add all settings column in the users table or it's ok to keep as i have them now? Settings can be updated by user while users table is updated by the system.
Should i split the user table according to users type? For example Artist table, fan table etc. that will store the appropriate registration and settings? Type of user needs to be in a column as is important for some functions of the site.
Regarding music table i was thinking to making a table for each genre that will store the uploads according to the genre specified by the user. Is this a good way of storing tracks to database or not? So when i want to call tracks of disco music i just use the disco music table.
Any help will be much appreciated.
not quiet sure I understand everything completely how your table is correlated, or what exactly you want or plan to do, but here is one idea about how to store genres in your database. And to connect it with your Setting table
First create table Genres in which you will store all genres. That table could look like this
Table: Genres
ID | genres_name | description etc.
ID - will be primary key auto increment
genres_name - will hold the name of genre (blues, jazz, disco...)
description - this column i added just if you want to add something specific by every genre it's not necessary
Next step is to create table Settings_genres. This table will store relation between your Setting table and Genres table and will look like this
Table: Settings_genres
settings_id | genres_id
So data in this table will look like this (for the setting ID 1 which will have 3 different Genres)
settings_id | genres_id
------------------------
1 | 2
------------------------
1 | 4
------------------------
1 | 5
------------------------
settings_id and genres_id will be primary key pair which means that you wont be able to store two identical pair int this table (You can have only one relation between one settings column and one genre column)
That is something called Many to many relationship and I'm sure that you can easily find more about that if you google it just a little.
When you want to pull data off from database which will show all settings and all genres you can do it with query like this
SELECT Settings.*, Genres.genres_name, Genres.description
FROM Settings
INNER JOIN Settings_Genres
ON Settings.ID = Settings_Genres.settings_id
INNER JOIN Genres
ON Settings_Genres.genres_id = Genres.ID
ORDER BY ID
Here is SQL Fiddle to see how it's look like.
When you want to pull data from settings table where that table is connected with specific genre you do that like this
SELECT Settings.*, Genres.genres_name, Genres.description
FROM Settings
INNER JOIN Settings_Genres
ON Settings.ID = Settings_Genres.settings_id
INNER JOIN Genres
ON Settings_Genres.genres_id = Genres.ID
WHERE Genres.genres_name = 'Rock'
ORDER BY ID;
This can also be achieved by this query which may be a little faster but let's not go into detail...
SELECT Settings.*, Genres.genres_name, Genres.description
FROM Settings
INNER JOIN Settings_Genres
ON Settings.ID = Settings_Genres.settings_id
INNER JOIN Genres
ON Settings_Genres.genres_id = Genres.ID
AND Genres.genres_name = 'Rock'
ORDER BY ID;
Here is FIDDLE for that...
So basically I suggest you to learn a little bit about relation between tables especially many to many relationship. And on than you will see how to improve your data table design.
Hope I help a little.
GL!
i think the way your table is, is okay. you dont have to split the table based on the type of users you have. but i think what you could use is font end technologies to allow users preform activities you want them, which is restricting them to only what you want them to do, they by controlling flow of information within the system. i hope that helps.
I have a rather special use case in front of me. There is to be an excel file with around a thousand entries (rows), each row represents something that the USER should pass judgment on.
Now, the entries are the same for everyone. The data that should be collected is
a) how many users like any given entry
b) what entries does any given user like
Since part of the app is already running and we have user accounts,
I thought of creating a table for each user (!) containing said excel information, adding a row for collecting the votes. I would create those tables by iteratin through the user list and creating tables like "userid_excelentries".
I don't think that's elegant. I would prefer to store the excel information only once in a table and only save the users' votes in the table "user".
The app is meant to display a table created form the excel table (I have the grid already done) and a row next to it with checkboxes. How do I structure this ? Temporary tables ? How do I store the information what each user has selected in the "user" table, since I don't know how many selections will be made a-priori ?
I had this crazy idea of actually handling the xls object through javascript, serializing it into a hash and storing that hash into a field in each user's row...but I have no clue if this is sane :o
We're facing a user count of exactly 272 - this is why I considered doing the "one table for each user" approach.
You can use 3 tables in your DB
users table
-----------
id
name
...
entries table
-------------
id
name
...
user_entries table
------------------
user_id
entry_id
user_response
To get all entries a certain user (i.e. Tom) likes you can do
select e.name
from entries e
join user_entries ue on ue.entry_id = e.id
join users u on ue.user_id = u.id
where u.name = 'tom'
and ue.user_response = 'like'
And to get the count of likes for each entry you can do
select e.name, count(ue.user_id) as likes
from entries e
join user_entries ue on ue.entry_id = e.id
where ue.user_response = 'like'
group by e.id, e.name
I am having a database design issue and i'm still pretty new to MySQL so I thought I would ask here. What would be the best way to get data for a chronological feed from multiple tables? For example a user does many things, they vote, comment, rate, ask questions. I save all this information in their respective tables "tblVote", "tblRate" etc, now the tricky part. a user can follow a user or many, so say you follow 3-4 people. Following allows you to see their interactions, voting, rating, commenting, asking questions etc in your feed (like facebook or something similar).
What would be the best way to get all the information from all 5 tables for every person they follow and then sort all of that chronologically? I Am assuming my current method (foreach follower grab all votes, comments, ratings etc and sort all would be terrible)
My working theory, so my working idea is to create a Interaction table, that has a column for the users id, the id of the other tables entry, and a type reference. so for example
User ID | InteractionID | Type
9 1232 Comment
10 80 Rating
9 572 Vote
Then you could just go ahead and grab all Interactions for each of the people they follow, sort that and then say grab the top 10? and query the individual databases to get the full info (time of comment, text of comment etc)
A many to many relationship exists between User and Follower. Since, Follower is also another user, this becomes a recursive many-to-many. When you decompose this relationship, you get a Association table or a gerund.
User_Follower {id, userid_fk, followerid_fk}
Both the userid_fk and followerid_fk are referencing to the User table.
Now, I am assuming you have a One-to-many relationship between User-tblRate, User-tblVote, User-tblPost etc.
So, you can write a join something like this:
select p.postTitle, p.postTag, ...,
c.commentId, c.commentData, ...
from (tblUser u INNER JOIN tblPost p
ON (p.userid = u.userid)) INNER JOIN tblComment c
ON (c.userid =
u.userid)
where u.userid in
(select userid_fk from user_follower where followerid_fk = 100)
orderby p.datetime_col ASC, c.datetime_col ASC
LIMIT 10;
100 is the user you want to get the information for.
The idea is that you just have one association table linking the User and Follower, then use simple joins to get the data for all the followees
Lets say I have users table:
| id | username | email | address |
And posts table:
| id | post | user_id | date |
When I want to show posts, each time I need to go users table to retrieve username from user_id. I want to avoid using JOIN for this simple data retreive so what I do is adding another coloumn to posts table:
| id | post | user_id | username | date |
This way I will not have to use JOIN to retreive username when showing posts
Do you think that this is better?
no. your alternative structure is vulnerable to inconsistencies (e.g. if a user changes his name; read about 3rd Normal form here http://en.wikipedia.org/wiki/Third_normal_form#.22Nothing_but_the_key.22)
why don't you want to use JOINs? have you set up approriate indexes?
I think it depends on the design and future, niy I will suggest you not to do that:
although from present respect, you will think it will be better performance to avoid join, but what if your application expand, and it is no good to use this unnormalized table structure.
For instance, if one of the poster changed username, how could you achieve that? to update the whole table? if your data could exccess 10Million tuples, it will be tough because update will lock the table in the process of updating.
thus I will not recommend this.
Join performance can be omit if your application needs frequently updating in that way.
If the [id] of [users] table is the primary key, I think it is good enough to use JOIN.
Alternatively, if you select limited number of posts, such as 10 posts, can also try this sql:
select id, post, user_id,
(select username from users where id = user_id) as username, date
from posts
limit 0, 10
I have a pretty typical user table setup for my web application:
user_id | username
--------------------
0 greg
1 john
... ...
Both fields are indexed and unique, so I can look up a user by id or username quickly.
I want to keep a friends table, and am not sure whether to store the user_id values or usernames in that table:
user_id_1 | user_id_2
--------------------------
or
username_1 | username_2
--------------------------
I am going to want to get a list of friends for a user, so it would be convenient to immediately have the usernames in the friends table instead of doing a join on the users table:
select * from friends where username_1 = 'greg';
If I'm storing user ids, I need to do a join then to get the usernames - will that be costly?:
select * from friends
where user_id_1 = x
join users where user_id = { all those results }
Using user ids allows me to let users change usernames flexibly, but I'm not letting them do that anyway. Any advice would be great.
Thanks
A join on the IDs won't be too bad. The ID may be smaller to store on disk. Also, I would imagine a list of friends would have something other than just user names, in which case, you have to join no matter what.
Well, as you said, using id semantics means you can change the username without having to deal with cascading effects. For most cases PK / UNQ + FK indexes will make joins thundering fast, but you may have a point for huge tables (for which you will eventually need some kind of external index, or other tool anyway).
The ID will be smaller if you use numeric values. Also the index search will be faster. Here you'll find the data types for MySQL 5.0.
Also I don't know how are you using index, but I'd recommend to add and auto-increment field. You can do that to a table, for an integer index like this:
ALTER TABLE `Database`.`tableName` ADD COLUMN `indexName` INTEGER NOT NULL AUTO_INCREMENT