I am creating a small database where the administrator will be able to purchase modules to assign to users. In addition, the admin will be able to un-assign a user from a module (letting go of that license) and reassign another user to the module. I would also like to keep a log of these assignments, in order to see how often these changes are being made.
My one option is to have one table of the type:
User_Licenses(user_license_id, user_id, module_id, date_from, date_to)
where the date_to remains blank for active users. This means that in order to see if a user has access to that module I’d have to check with:
SELECT user_id FROM User_Licenses
WHERE user_id = 1
AND module_id = 1
AND date_from <= TODAY
AND date_to = NIL
My other option is to have 2 tables of the type:
User_Licenses(user_license_id, user_id, module_id, active_user_log_id)
Active_User_Log(active_user_log_id, date_from, date_to)
where I would make a log entry every time a new license was assigned and update the date_to field every time a license was un-assigned.
Now I understand they are essentially the same thing, with a little more programming overhead on the second option, yet to check if a user has access to a module I know only have to do:
SELECT user_id FROM User_Licenses
WHERE user_id = 1
AND module_id = 1
and the log is logically separated from the “everyday checking”
What I’d like to know is what is more commonly used, and how much slower the first SQL statement is to the second.
This is for a webapp, the number of users will likely not be over 100, and the changes in assignments of users to modules should be minimal. The checking of access to a module will be on a daily basis, and the users will be assigned to multiple modules.
Thanks in advance for your help.
I’ll give my opinion, but there are more questions to be answered and topics to be addressed first.
To start, if you use the first case, you are also saying that the concept of an “active user” is not that important to you. In the second case, you are saying that it is. In other words, you are only talking about one kind of query here, but there will also be needs for other queries, and if they deal with “active users” that should help you decide.
Also, I suspect that when you write the code to compare nulls, you will have to say “date_to is null” instead of “date_to = nil”. Databases often (almost always?) differentiate between NULL and blank, and one way is by how you compare columns to nulls.
I also think that based on my experience with Licensing, you license something for a specific amount of time, so the one table method, with NULL as an indicator, does not appeal to me. I would rather see a date, and then you could ask if the current date is after the expiry date. This issue would not be a deciding one, but I thought it reasonable to mention.
Finally, the table Active_User_Log sounds fishy. Do you also have a USER table? I would have gone with a User table, and added a status to that table, for example USER.STATUS. You would still have to join on the License table, but the tables would reflect reality a little bit better in my opinion.
My answer? The speed difference between the two queries would not be noticeable, as long as you indexed the underlying tables appropriately. But I would vote for the two table approach, and keep the contents of a single table specific to that entity.