Database Design – SQL Schema Design Advice

database-design

This question contains no concrete programming question, i would only like to hear some ideas, on how it would be appropriate to design my database.

So recently I started designing an application where the main goal is the following:

  • There are users
  • The users can create reports (they some get points for creating one)
  • They can provide additional data (additional points)
  • They can view others reports
  • They can unlock additional data about other peoples records, using
    their own points

The point of my question is: How to store and/or calculate the users current points?


1. First method

The schema, and points-calculating method I first thought of looks like this:

schema

The users (can) have reports, the reports (can) have report details, which are connected to a report detail type, which contains the information about how much points it costs to unlock, or to create a detail from a given type. The user also (can) have transactions which contains the unlocks by the user.

From this schema i could create a query which returns, how much score the user have created, and how much he/she has spent with transactions. I could the substract the two, and i have the current score.

The problem with this: If the score for one report detail type gets modified the score for all users will be modified. Which i don't want to.


2. Second method

The second idea i had is to simply store the users points in a column in the users table, and whenever he/she tries to create/unlock something, update it. The schema could be identical, but there would be an extra column in the users table. For some reason it feels really unprofessional, and it also feels like, that i would store data, where it doesn't belong.


3. ???


I would really appreciate any ideas, on which one of these would be better and why! If I'm started thinking about the problem in a completely wrong manner, I also would like to know about a better solution! Thanks for any help!

Best Answer

The third option is to keep a transaction log of points transactions.

Use the schema from your first option to record the "going rate" for points. Whenever you have a transaction that either gives or takes points away from a user, write a record (or multiple records) into a points transaction log table.

The transaction log table will have a FK to USERS and a date/time to indicate when the transaction took place. It could also have FK's to the items which generated the points, such as FK's to your TRANSACTIONS and REPORT_DETAILS tables, that's up to you.

Most importantly, the transaction log table will have a column for the number of points awarded(+) or spent(-). To get a user's point balance, you run a sum of all transactions for the user up until the current time. The important thing is to keep a record of how many points were given or taken for that user, at that time regardless of what may happen to other users or at other times.

If performance becomes an issue, you can keep the user's current point total on the USERS table, but this should be denormalized data based on the transaction log details. If you do this, then you need to have controls in place to make sure you're managing this redundancy appropriately.

Related Question