I've been programming and using a survey software for more than three years. It began as a simple survey system, with a basic 'users' SQL table, as you can find, for instance, in most CMS's. I initially planned to use the program two or three times, with 30 users or so for each survey.
Today, the program has grown and is used for one or two surveys every month. A survey may have hundreds of users, which makes the table awfully long and confusing.
I can't find a best way than a classic user list, though. I though of creating a new table for each survey, but I feel it's asking for problems. What I do now is to archive the complete SQL database when a survey is finished, which is convenient enough for now but will turn into a nightmare when I'll have to quickly find the results of an old survey.
I'm confident I'm not the first one to encounter this problem and would be happy to know how you solved it. Are there some kind of best practices for it?
Thanks!
One solution is to maintain two tables. Users and Users_History.
Once a survey is complete, you can move the data to users_history. That way, DB that affects app performance would stay within a manageable size. For analysis purpose, data would always be available in history table.
If the set of users for each survey is distinct (the same person in two surveys would have two different user accounts), you could add a column to users referencing the surveys table.
ALTER TABLE users ADD COLUMN survey INT NOT NULL;
ALTER TABLE users ADD FOREIGN KEY (survey)
REFERENCES surveys (id)
ON DELETE CASCADE;
If you want to allow users that aren't associated with a survey, allow the survey reference to be NULL and set the foreign key to ON DELETE SET NULL.
When it comes time for you to operate on the users table, use the column to get only the users that are a part of the survey of interest.
Related
I am building a database for my application using Mysql, contains 2 tables in which one table will have user details and other table will have all user's activities(say posts,comments,..). I have 2 approaches for this PS.
Group all users activities under one table(say useractivities).
Maintain specific activities table for each user(say user1activity,user2activity,...).
If we go with approach 1, it builds time complexity in case of more users.
with approach 2, eats up database. which design will show less time and space complexity?
For better database maintain, you have to go with the first approach because you can normalize data easily.. and the perfect way to manage database structure, Need to take care of below points
You have to give proper indexing in user_id field for fast result in join query.
In case of large number of records in one table, then you can create another table like user_activities_archive for store old activities. in the regular period, you can move an old record from user_activities to user_activities_archive
You can create multiple tables for user_posts, user_comments instead of user_Activities for more splitting data and different structures of the table, for example you can manage replyto_id in the comment table and user_post table might have title field.
In the second approach for cerate tables for each user, there are many limitations like
Very hard in case of Table Joining with other tables
In case of fetch all user's activity records, you cant do it.
A number of the user base of your application.
Limitation of a number of tables in the database.
Create more complexity in edit update or delete user records.
If the user is not active (just registered) then separate user table useless.
As juergen d mentioned in the comment, approach 2 should not be used.
However I would consider splitting useractivities into different tables if the possible user activites are different from each other to avoid unneccessary column.
Example: A comment table with information about who made the comment (foreign key to user table) and the comment itself. + A foreign key to another user activity to wich the comment was made.
The comment column in the above table does not make sence for say, just a like of a post, so I would have created a different table for likes.
I am setting up a database using MySQL with the goal of storing data for a potentially large number of unique users. Each user will have some basic data associated with them - a unique username, when they joined the service, how many times they have used the service, in addition to a set of their personal preferences. I am planning on keeping one table called 'Users' dedicated to these fields.
However, there is a bunch of data with a specific schema that will be collected about that user during each session that they use the service. This data includes which user performed this session, the date of the session, what the user did, etc.
My thought process is the following: if I use a single table for users that includes data on each of their sessions, this seems inefficient because there would have to be either a column for each unique session, or a column containing more or less an array or list of sessions. If I wanted to keep this data for an indeterminate number of sessions, then the one-per-column idea would break down, because I believe there is a column limit. Updating an array within a single column also seems to be frowned upon, I think for reasons having to do with preserving the integrity of the data and maintaining the best possible organization.
So it seems like I want two tables, one for users, and another for sessions. Every time anybody completes a session, data about that session will be created as a new row in the 'Sessions' table, and each row would also have a foreign key linking that session to the particular user who completed it.
Is this a correct line of thought? If not, how should I think about this?
Thanks
I would say you're pretty close. You should separate users and sessions, and you're looking at modeling a relationship. Each session only has one user, so it's a one-to-many relationship.
1 User (1 Row in the "Users" table) can have many Sessions (1 Row in the "Sessions" table)
The Foreign Key is the User ID in the Sessions table. This links each unique session (Which will have it's own Session ID I'm assuming) back to a unique User in the Users table.
If you're looking at a massive volume of users, which means a ton of sessions, you may want to consider options on how to help the sessions table not grow to be extremely huge and slow to query. If you're collecting this data on a daily basis, consider that you could "Partition" the table on dates:
Partitioning on DateTime in MySQL
edit: typos
My experience with databases is limited so I am not sure of the best way to ask this question, so I am going to break it down as simply as possible. I've built an ASP.net application with a mySQL database using NHibernate that has multiple users that can log in and all work on the same table (let's say of forum posts). So we have our users table and our food table.
Now I am looking for the best way to split these users into groups, very much like different companies. So The users from the same "company" can log on and see all there other company users and edit/create posts view-able by said "company".
I am looking for the most scalable (fastest with 1000's of companies) way to do this. Should I
1: Have a universal table for users and posts with a foreign key? So everything is stored on the same SQL table but their view of this table is restricted by the company ID. I see this being the easiest one to build, but will 1000's of companies accessing the same table with this be slow/problematic?
2: Create a new posts table for every company? So every user from a company accesses their own table of posts. To scale up would this be more efficient/faster if there were thousands of companies?
A quick explanation of the best method would be really appreciated. But also pointing me to documentation/resources would be amazing! Cheers.
I strongly suggest option 1.
You should create company table with companyID as primary key. Use companyID as foreign key in users table and food table.
This is regular approach and works well in most of the cases.
It would be very complicated to maintain 1000's of tables in the application.
Users and food table will be already indexed by company ID so the filtering will be very fast.
I am making a MySQL database and am fairly confident I know how to normalize it. However, there is an issue I am not sure how to deal with.
Say I have a table
users
----------
user_id primary key
some_field
some_field2
start_date
user_level
Now, user_level gives the user's level, which can be 1,2,3,4,5 say. But as time passes the user may change levels. Obviously if they change levels I can simply do an UPDATE to the users table. But I want to keep a historical record of the users' past levels
For this reason, I am considering a new table called user_level_history
user_level_history
--------------
id autoincrement primary key
user_id
level_start_date
and then modify the users table:
users
----------
user_id primary key
some_field
some_field2
start_date
user_level_history_id
Then to get the user's current level I check the
user_level_history_id = user_level_history.id
And to get the user's history I can SELECT from user_level_history all rows with the user_id and order chronologically.
Is this the standard way to do this? I can't imagine I'm the first person to come across this problem.
One more point: I am imagining less than 5000 users. Would having many, many more users require a different solution?
Thanks in advance.
I think that could be designed like this:
Have a table for level information like value(1,2,3,4,5) , description ...
Have an association table for user_level_history containing user_id, level_id,level_start_date ...
Have a foreign key from level table to user table with the role user-active-level.
You need to develop a mechanism that when user level is changing, inserting to history table occurs.
No, you aren't the first. Querying temporal data is a common requirement, especially in data warehouse/data mining.
The relational data model doesn't have any native, built in support for storing or querying "temporal data".
A lot of work has been done; I have a book by C.J.Date et al. that covers the topic decently: "Temporal Data and the Relational Model". I've also come across several white papers.
One typical, reasonably simplistic approach to storing a "history" is to have a "current" table (like the one you already have, and then add a "history" table. Whenever a row is changed (inserted,updated,deleted) in the "current" table, you add a row to the "history" table, along with the date the row was changed. (You can store a copy of the pre-change row, or a copy of the post-change row, or both.)
With this approach, there's no need to add any columns to the "current" table.
The best way to describe this scenario is to use an example. Consider Netflix: do they
store their orders (DVD's they mail out) in a separate table from their member lists (NOT members table, but a joiner table of members and movies--a list of movies each member has created), or are orders distinguished by using additional information in the same row of the same table?
For those not familiar with Netflix, imagine a service that lets you create a wish list of movies. This wish list is subsequently sent to you incrementally, say two movies at a time.
I would like to implement a similar idea using a MySQL database, but I am unsure whether to create two tables (one for orders and one for lists) and dynamically move items from the lists table to the orders table (this process should be semi-automatic based on the member returning an item, where before a new one is sent out, a table with some controls will be checked to see if the user is still eligible/has not gone over his monthly limit)...
Thoughts and pros and cons would be fantastic!
EDIT: my current architecture is: member, items, members_items, what I am asking is if to store orders in the same table as members_items or create a separate table.
Moving things from one database table to another to change its status is simply bad practice. In a RDBMS, you relate rows from one table to other rows in other tables using primary and foreign key constraints.
As for your example, I see about four tables just to get started. Comparing this to Netflix, the grand-daddy of movie renting, is a far-cry from reality. Just keep that in mind.
A User table to house your members.
A Movie table that knows about all of the available movies.
A Wishlist or Queue table that has a one-to-many relationship between a User and Movies.
An Order or Rental table that maps users to the movies that are currently at home.
Statuses of the movies in the Movie table could be in yet another table where you relate a User to a Movie to a MovieStatus or something, which brings your table count to 6. To really lay this out and design it properly you may end up with even more, but hopefully this sort of gives you an idea of where to begin.
EDIT: Saw your update on exactly what you're looking for. I thought you were designing from scratch. The simple answer to your question is: have two tables. Wishlists (or member_items as you have them) and Orders (member_orders?) are fundamentally different so keeping them separated is my suggestion.
A problem with storing orders in the members table is that there's a variable number (0, 1, or several) of orders per member. The way to do this using a relational database is to have two separate tables.
I feel like they would store their movies as follows (simplified of course):
tables:
Titles
Members
Order
Order_Has_Titles
This way an order which has a foreign key to the Members would then have a pivot table as many orders could have many titles apart of them.
When you have a many to many realtionship in the database you then need to create a pivot table:
Order_Has_Titles:
ID (auto-inc)
Order_FkId (int 11)
Title_FkId (int 11)
This way you're able to put multiple movies apart of each order.
Of course this is simplified, and you would have many other components which would be apart of it, however at a basic level, you can see it here.