I have this scenario where I have three entities Book, Review, comment and have the following tables:
Books (Id, ReviewCounts)
BookTranslations (BookId, LanguageId, IsDefault, Title, Description)
Reviews (Id, BookId, CommentCounts)
ReviewTranslations (ReviewId, LanguageId, IsDefault, Content)
Comments (Id, ReviewId, Content)
Now, I want to add two other entities to the design, Vote and Report. The vote entity represent a vote the user do on all of the previous three entities, Book, Comment, Review. And the report, where the user should be able to report fake Books, inaccurate Reviews, hate and illegal Comments and fake User profiles.
The problem is, I need now to add three tables for the vote BookVotes,CommentVotes, and ReviewVotes. And four different tables for the report UserProfileReports, BookReports, ReviewReports, CommentReports.
Now, I think about adding one base table so to speak, called Entities, and another table EntityTypes, where EntityTypes contains data like "Book,Review,Comment". And the same primary key will be in Entity and Review or Entity and Book and so on. This way I will solve the vote issue, but not the report because the user can report a user profile which is a User entity. It doesn't make any sense to add the User entity to the list of the three aforementioned entities and "derive" it from the Entities "base" table too.
To be honest, I don't think the usage of one "base" table Entities make sense either, because conceptually the book, review, and comment are three totally different entities.
So, my question is, should or shouldn't I go with the "base" table solution, and if so, how should I solve the report problem?
I would NOT go with the single "base" table idea. Since a single vote can only be about either a book or a comment or a review, but not about multiple items, it makes more sense to me to keep them in separate tables. Same for reports.
Databases with lots of small tables tend to perform better than databases with just a few big tables, so unless there's a modelling reason to combine the entities, I wouldn't do it.
Related
I have a database structure issue I am looking for some opinions on.
Let's say there is a scenario where users will use an application to request materials.
There is the need to track who the requester is.
There are three possible "types" of requesters. An individual (Person), a Department, and the Supplier supplying the materials themselves.
In addition the Supplier object needs to be related as the Supplier as well.
So the idea is in the Request table there is a RequestedByID FK. But the related requester has such a different structure for the data for each that it would require a completely denormalized table to related back to if it were made just a single table (people have different properties than departments, and suppliers).
I have some ideas on how I might handle this but thought the SO community would have some great insight.
Thanks for any and all help.
EDIT:
pseudo structure:
Request
RequestID
RequesterID
Department
DepartmentID
DepField1
DepField2
Person
PersonID
PersonField1
PersonField2
Supplier
SupplierID
SuppFiel1
SuppField2
Department, Person, and Supplier all have separate tables because they differ in their properties quite a bit. But each of them can serve as the Requester of a Request (RequesterID). What is the best way to accomplish this without one (denormalized table) full of the different possible requesters?
Hope this helps. . .
You need what is in ER modeling know as inheritance (aka. category, subtype, generalization hierarchy etc.), something like this:
This way, it's easy to have different fields and FKs per requester kind, while still having only one REQUEST table. Essentially, you can varry the requester without being forced to also vary the request.
There are generally 3 ways to represent inheritance in the physical database. What you have tried is essentially the strategy #1 (merging all classes in single table), but I'd recommend strategy #3 (every class in separate table).
You could have two different IDs: RequesterID and RequesterTypeID. RequesterTypeID would just be 1, 2, or 3 for Person, Department, and Supplier, respectively, and RequesterTypeID paired with RequesterID would together make a multi-attribute primary key.
What Jack Radcliffe suggested is probably the best option. So I'd just add an alternative option:
You might also consider having 3 requests tables... One for ppl requests, one for suppliers requests, and one for departments requests... So you don't need to explicitly store the RequesterTypeID, since you can deduce it from the name of the table... You can then create the table Jack Radcliffe as a view, by "uniting" all the 3 individual tables...
Also, if you implement Jack Radcliffe approach, you can create 3 views to simulate the 3 tables I've mention... So then you can use whichever table/view is best for each situation, and if you want to change from approach A to B it's really easy too...
What I like about Jack Radcliffe's thought is if you store them in a separate table or make the sql statement generic to handle any number passed in by the application, they can be expanded e.g. manufacture, entity, subsidiary, etc
However, you choose the expansion will entail overhead.
I have a come up with the following schema for a client of mine. Does anything look off here especially the Order Line Items. Should i use inheritance. I'm pretty sure that this site will only allow you to order courses, lessons, and giftcards, and that's it
Any feedback would be appreciated
Just my thinking on the design:
You have Courses, Lessons and GiftCards tables for the possible purchase objects, and OrderLines contains IDs for each of the tables. But in case a customer will purchase a Lesson and a GiftCard, they should be shown as 2 lines in the order. Also, what you will do if your client will want to trade more objects?
Therefore I think it might be better to redesign this part, like this:
OrderLines rename to OrderItems;
add ItemType table with 3 rows: Courses, Lessons, GiftCards;
add Items table with (ItemId, ItemType, Title, Price, LanguageCode, SortOrder, etc.) fields.
This way it will also be possible to add reviews not only for Lessons, but for all possible items.
You will have to come up with the preferred way to keep fields for the Items details. Right now Courses and Lessons share a lot of fields, therefore it might be reasonable to move all of them into the new Items table, as such fields seems also to be valid for the GiftCards also. And in case you have some specific details, like for GiftCards, you might add specific tables, like GiftCardItems with Items.id and a set of special fields not shared with other Item types.
A minor note: I would split Users into a couple of tables, as I suppose that this table will contain both, customers and support stuff. This means that this table might grow big (depending on how many customers are expected). Maintaining so many fields in a single table might be problematic when table will grow in number of rows.
And I agree with Matt — it is difficult to tell anything without requirements.
It is really hard to tell without knowing the requirements from your client. Everything looks good but I can't really tell if it is all inclusive of what the client wants without their requirements documentation.
I have the following situation.
We want an reputation table to evaluate Users And Companies.
This reputation table would store the reputation given by an Company to User and vice-versa.
It was suggested that we should create two reputation tables, one for the Users and another for the Companies, both with the same columns.
I dont think thats the best way but I cant find another solution.
Is there any other way we could do that?
thx
I don't think your approach is bad; another solution would be to have an abstract Entity table, with each User and Company having its own Entity record (and thus entity ID); then you only track reputation between two entities in a single Reputation table.
Another approach is to have a Reputation table with a user ID, a company ID, and a type (or direction, or whatever seems logical in your model) field which indicates whether it is reputation for the company given by the user, or the other way around. Seems less normalized though.
You would have a table for the company containing a unique key for that Co. Same for the user.
I assume the relationship between Co and User is many-to-many.
You need one more table containing both keys, for Co and User, and two fields, one for Co-rep and one for User-rep. The Co-key and User-key combination would be unique entries for this table.
Consider we have a database that has a table, which is a record of a sale. You sell both products and services, so you also have a product and service table.
Each sale can either be a product or a service, which leaves the options for designing the database to be something like the following:
Add columns for each type, ie. add Service_id and Product_id to Invoice_Row, both columns of which are nullable. If they're both null, it's an ad-hoc charge not relating to anything, but if one of them is satisfied then it is a row relating to that type.
Add a weird string/id based system, for instance: Type_table, Type_id. This would be a string/varchar and integer respectively, the former would contain for example 'Service', and the latter the id within the Service table. This is obviously loose coupling and horrible, but is a way of solving it so long as you're only accessing the DB from code, as such.
Abstract out the concept of "something that is chargeable" for with new tables, of which Product and Service now are an abstraction of, and on the Invoice_Row table you would link to something like ChargeableEntity_id. However, the ChargeableEntity table here would essentially be redundant as it too would need some way to link to an abstract "backend" table, which brings us all the way back around to the same problem.
Which way would you choose, or what are the other alternatives to solving this problem?
What you are essentially asking is how to achieve polymorphism in a relational database. There are many approaches (as you yourself demonstrate) to this problem. One solution is to use "table per class" inheritance. In this setup, there will be a parent table (akin to your "chargeable item") that contains a unique identifier and the fields that are common to both products and services. There will be two child tables, products and goods: Each will contain the unique identifier for that entity and the fields specific to it.
One benefit to this approach over others is you don't end up with one table with many nullable columns that essentially becomes a dumping ground to describe anything ("schema-less").
One downside is as your inheritance hierarchy grows, the number of joins needed to grab all the data for an entity also grows.
I believe it depends on use case(s).
You could put the common columns in one table and put product and service specific columns in its own tables.Here the deal is that you need to join stuff.
Else if you maintain two separate tables, one for Product and another for Sale. You use application logic to determine which table to insert into. And getting all sales will essentially mean , union of getting all products and getting all sale.
I would go for approach 2 personally to avoid joins and inserting into two tables whenever a sale is made.
2 part question:
1st
What is the best way to setup a table/relationship structure given the following scenario: I have many tables that store different kinds of data (ie: books, movies, magazine - each as different tables) and then one table that stores reviews that can link to any of the table types. So a row in the review table can link to either books or magazines table.
How I have it now is that there is a 3rd table that defines the available tables and gives them an ID number. There ends up being no true relationship stored that goes from Reviews to Books. Is this the best way to do this?
2nd
How do I represent the fake relationship in Entity Framework? I can do a query that would join the 3 tables, but is there a way to model it in the table mapping instead?
The other way to think of it is to consider BOOKS, MOVIES, MAGAZINES as sub-types of REVIEWABLE_ITEMS. They probably share some common characteristics - without knowing more about your problem domain it would be hard to be sure. The advantage of this approach is that you can model REVIEWS as a dependency of REVIEWABLE_ITEMS, giving you both a single table for Reviews and an enforceable relationship.
edit
Yes, this is just like extending types in the OO paradigm. You don't say which flavour of database you're intending to use but this article by Joe Celko shows how to do it in SQL Server. The exact same implementation works in Oracle, and I expect it would work in most other RDBMS products too.
It really depends on how you want to access/view the reviews.
I would implement one table for each kind of revew: one for books, one for movies, etc. with a one-to-many relationship for each of them (between books and books reviews, movies and movie reviews, etc). If you need all the reviews in one table, create a view which selects all reviews with a UNION ALL.
Either you include a concept "reviewable", which can be either a book or a magazine or ... , and to which "reviews" can refer, or else you can have a concept "review", which can either be a "book review" that can reference a book, or a "magazine review" that can reference a magazine, or a "newspaper review" that can reference a newspaper, ...
Because truly relational systems do not exist, you cannot do without explicitizing one of those two abstractions in your database design. (Unless perhaps if you are willing to implement a lot of trigger code.)