Table which contains parent_id in same table while using a foreign key - sql

I have a table which will contain various categories. The following is a minified table structure:
tb_categories
category_id
category_name
category_parent_id
I created a foreign key constraint on category_parent_id on the category_id so data integrity can be held within the same table.
First question is, is it good practice to have a foreign key on the same table. From my way of thinking I am thinking that yes in such a case, it is a good practice.
Second question is, what is the best approach on how to store the global parent entity?
I came up with the following methods:
Method 1: category_parent_id can store nulls and the only null is the global parent category entitled All
Method 2: category_parent_id cannot store nulls and the global parrent ALL will contain its same category_id. Therefore, for only this category, both category_id and category_parent_id will be identical. Without nulls, I cannot insert this category_parent_id as 0 since 0 does not exist as a category_id
Method 3: Not having a global parent and there will be different 'parents'. For example, having Audio, Visual as parents and MP3, WMA as Audio's children and MPEG, AVI as Visual's children. Throughout this method, the same principles of methods 1 and 2 applies.
Method 4: This is the least method which I prefer which includes in not having this foreign key constraint and thus the global parent can be set to 0 which does not exist in any other category.
Any suggestions? As I am looking for the best practice and not something that 'just works'.

It is normal to have a table refer itself. There are a lot of real world scenarios that need this situation (Employee -> Manager is a famous textbook example).
And, you will end up having a "global" parent whether it is a single global parent or multiple global parents. So you need to come up with an approach.
I prefer method 1 - an element without a parent will have no parent at all, because, well, it exactly realizes your business rule.
Having a 0 or referring self as parent will create problems when you have complex queries

Related

Class Diagram: In A Composition Relationship Should a Child Class Always Have An ID Field?

I'm having a hard time converting my database tables and foreign keys to a class diagram with classes and associations.
My question is:
"In in a composition relationship, should a child class always should have an ID field?".
In my CD, there are 2 compositor classes: PurchaseItem and PurchaseFinisher, which composite Purchase class. PurchaseItem already comes with an ID field from its table but, PurchaseFinisher doesn't because it is filtered by the id_purchase and id_payment_method foreign keys.
thanks in advance.
This is my DB diagram:
I can't see redundancy in between Purchase or Product, as you said. Could you, please, show me that based on my DB diagram? My tables are well modeled (hope so). My fault is in the classes definition.
In a class diagram, no class requires an id property: each class instance (aka object) has its own identity with or without explicit id property.
In a database, you need of course an explicit id property to uniquely identify the object among others in the database and find it back. By the way, you may annotate such properties with a trailing {id} . UML does not define any semantic for it, but it is in general sufficiently expressive to help database designers.
In the case of composition, the main question is whether a composed object can easily be identified by alternate means. There are several related ORM database techniques, for example:
you can use the owning object’s id together with another property if this is sufficient to identify the element. The two together would make a composite primary key in database.
you can use a unique id to identify the object (surrogate primary key) and use the id of the owning object as foreign key.
For PurchaseItem you have everything that is needed, although the diagram does not tell which of the two approaches you’ll use (e.g is the id unique globally, or unique within the purchase?).
But for PurchaseFinisher it is unclear if you could uniquely identify an occurence. If a payment method can only be used once per purchase, it’s fine as it may be used to identify the object.
If it would be allowed to pay two times the same amount (half of the overall price) in the same currency with the same payment methods, you’d have undistinguishable duplicates. So, some kind of identifier will be needed from the database point of view.

Parent & Child FK'ing to same table

What is best practise when a parent & child table both FK to the same table?
Parent > Child(ren)
CommonAttributes: Sex, Age, Height, Weight
Is it better to directly reference the common table:
CommonAttributes > Parent(s) > Child(ren)
&
CommonAttributes > Child(ren)
Or use a reference table:
RefTable: CommonAttributes_Id, Parent_Id(null), Child_Id(null)
I think the first method works OK (with regards to EF) but it is a bit of a circular reference. Is it better to use a reference table to define the constraints?
There are several approaches to this and the one you need depends on your business needs.
First, can a child record have more than one parent? For instance you might be modelling an organizational structure where an employee can have two supervisors. If this is true, then you have a one to many relationship and need a separate table for this model to work.
If you are guaranteed to have only one parent per child (but each parent might have a parent (building a hierarchy), then you can model this is one table. The table structure would include the Primary key, say UserID and then a nullable column for the parent such as ParentUserID. Then you can create the foreign key to the field in the same table.
ALTER TABLE dbo.Mytable ADD CONSTRAINT FK_Mytable _UserPArent FOREIGN KEY (ParentUserD) REFERENCESdbo.Mytable (UserID)
If you want to build a hierarchy in a query, you then use a recursive CTE to get it. See example here:
https://msdn.microsoft.com/en-us/library/ms186243.aspx
Another time you might want to build a separate table for the child parent relationship is if only a small portion of teh records in the main table would have parent child relationships. For instance suppose you had a people table that stored, sales reps and customers. Only sales reps would have a parent child relationship. So you would want a separate SalesRepHierarchy table to store it which woudl make querying more straightforward.
While in general you woudl want to create hierarchies in a recursive CTE, there are special cases when it might be faster to pre calculate the hierarchies. This is true if the hierarchy is frequently queried, the CTE performance is slow and you have control over how the hierarchy is built (preferably through an import of data only) and if it changes fairly rarely (you would not want to be rebuilding the hierarchy every minute, but a once a day import can be accommodated. This can greatly speed up and simply querying for the whole hierarchy, but is not recommended if the parent child relationships are created and changed constantly through the application.

How do I structure a generic item that can have a relationship with different tables?

In my example, I have a watch, which is an indication a user wants notifications about events on a different item, say a group and an organization.
I see two ways to do this:
Have a groupwatch resource, with a groupwatch table, with id,user,group (group FK to group resource and table); and a orgwatch resource, with a orgwatch table, with id,user,organization (org FK to organization resource and table)
Have a generic watch resource, with a watch table, with id,user,type,typeid. type is one of group or organization, and typeid is the ID of the group or organization being watched.
Since both of them are watches, it seems a waste to have two different tables and resources to watch 2 different objects. It gets worse if I start watching 4, 5, 6, 20, 50 different types of resources.
On the other hand, a foreign key relationship appears impossible if I just have a generic typeid, which means that my database (if relational) and my framework (activerecord or anything else) cannot enforce it correctly.
How do I best implement this type of "association to different types of record/table for each record in my table"?
UPDATE:
Are my only choices for doing this:
separate tables/resources for each watch type, which enables the database to enforce relational integrity and do joins
single table for all watches, but I will have to enforce relational integrity and do joins at the app level?
If you add a new type of resource once every six months, you may want to define your tables in such a way that adding new resources involves changing data definitions. If you add a new resource type every week, you may want to make your data definitions stay the same when you add new types. There's a downside to either choice.
If you do choose to define table in such a way that the types are visible in the table structure, there are two patterns often used with type/subtype (aka class/subclass) situations.
One pattern has been called "single table inheritance". Put data about all the types in a single table, and leave some columns NULL wherever they do not apply.
Another pattern has been called "class table inheritance". Define one table for the superclass, with all the data that is common to all the types. Then define tables for each subtype (subclass) to contain class specific data. Make the primary key of the subtype tables a duplicate of the primary key in the supertype table, and also declare it as a foreign key that references the primary key of the supertype table. It's going to be up to the app, at insert time, to replicate the value of the primary key in the supertype table over in the subtype table.
I like Fowlers' treatment of these two patterns.
http://martinfowler.com/eaaCatalog/classTableInheritance.html
http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
This matter of sharing primary keys has a few beneficial effects.
First, it enforces the one-to-one nature of the ISa relationships.
Second, it makes it easy to find out whether a given entry belongs to a desired subtype, by just joining with the subtype table. You don't really need an extra type field.
Third, it speeds up the joins, because of the index that gets built when you declare a primary key.
If you want a structure that can adapt to new attributes without changing data definitions, you can look into E-A-V design. Be careful, though. Sometimes this results in data that is nearly impossible to use, because the logical structure is so obscure. I usually think of E-A-V as an anti-pattern for this reason, although there are some who really like the results they get from it.

One to One with constraint and inheritence

I have been questioning a certain scenario if it could benefit from using a one to one relationship in my ERD. I have a table called library with a FK called typeID from a table called element type. Essentially the element types have a sibling relationship with element as the parent and each item in the library is one of those types. The library is mainly used to create a hierarchy amongst the elements and other properties of how they exist in the library. If I add a column for every property of each type of element most columns would be virtually empty because not every element type has every property of the others. Also there are some other tables that are using the library items id where I want to put a constraint on what types of elements can be a foreign key for that table because not every element type can have that relationship. I was wondering if it is a good idea to use 1 to 1 where there is that same constraint on what type of element from the library can exist in the table, then add the unique properties. For example tableXYZ can only have items where typeID from library = 1 and all the 1 types are always in it. It seems like a good way to simulate object inheritance/generalization. Also all the tables connecting to library needing a specific type of element for the FK relationship could connect to the extended 1 to 1 table which already has that constraint so they don't have to. Also some of the elements are extensions of each other, could you have 1 to 1 then extend 1 to 1 again? Is this a legit idea? Will it even work? Is there anything I am not seeing here?
fyi the DB is postgreSQL
You might want to look into two techniques: class-table-inheritance and shared-primary-key
By applying these two techniques to your case, you may end up with a simpler, yet more powerful design than the one you propose. In some cases, you can dispense with the TypeID entirely, because a join between the generalized table and the appropriate specialized table will yield precisely the objects you are looking for. In addition, because the join is on two primary keys, the join will be relatively fast.

Grouping records with or without a foreign key constraint

I have a table containing objects, something like this:
PK ObjectId
FK ObjectTypeId
Description
etc
The objects need to be grouped. I have been given a number of suggestions, all of which 'work' and some I like more than others. None of them are perfect so I'm struggling to settle on any particular model.
1/ Add a self-referential foreign key. This is clean but not ideal because (a) there is no logical parent (it's a group, not a hierarchy) and (b) it is potentially a pain for LINQ-to-SQL to traverse a self-referential hierarchy - would need to check to see if the current object is a 'parent' or a 'child' object, etc.
PK ObjectId
FK ParentObjectId
2/ Add a parent table & a foreign key. This adds constraints but the Group table doesn't contain any useful information - it exists only to provide a GroupId constraint & identity.
Table Object
PK ObjectId
FK GroupId
Table Group
PK GroupId
3/ Add a GroupId without a constraint or foreign key. No data integrity. The theory is that when a new object group is inserted, each object is given GroupId = the first assigned ObjectId. Probably the simplest & most practical solution.
e.g.
ObjectId GroupId
...
15 10
16 16
17 16
...
21 16
22 22
My question is which of these is the best in theory and/or practice, and why. Or, please tell me a better way to do this! I personally like (2) because it is normalized, but am told that a table with just one field is bad design. Thoughts and suggestions?
For option two, you can always add additional fields, for discriptions, display orders, and GroupParentID, for multiple levels of grouping. Also, you can implement securit on these grouping structures.
In our application we use that structure.
From the limited info you present it is difficult to recommend an option, because the method depends on your usage of the tables. Storing the data is one thing, but using it is a completely different issue. All three store the data is a way possible to retrieve it, however what queries will you need to construct to load it, aggregate it, and search it?
I would implement each method, populate with a small set of data and try to write a few queries to gather data as your application would. Any problems or difficulties in using the table design will become apparent then.
You should always design your tables so data retrieval is fast and easy. You shouldn't have to fight your tables to get your data out. If do you find yourself fighting with your tables to get the data out, then you designed them poorly. Your table structure should make your life easier not harder.