Parent & Child FK'ing to same table - sql

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.

Related

SQL multiple reference

I’m in a dilemma choosing the best strategy to model my database.
Let’s say I have a two tables: Variable(ID) and Object(ID).
Now, an entry in Variable may reference another entry in Variable or in Object.
To model this, one approach is creating 2 mapping tables:
Variable_Variable(variable_id, variable_id), Variable_Object(variable_id, object_id)
The other approach is to have in the Variable table two reference columns:
Variable(ID, parent_variable_id, parent_object_id).
If this variable references another variable, then the parent_object_id is null and vice-versa.
I feel first approach is neater, but second approach is faster when querying the database.
Is there any standard to apply in this cases? Which is the usual approach for these cases?
Thanks,
Danny.
Given that all relations are 1:1 I would go with your second approach of having parent_variable_id and parent_object_id columns in your Variable table.
You could then have a CHECK constraint to ensure that only one or the other column contains a value (or neither, if your variables don't have to reference a parent).
Another alternative that you didn't mention is using a single mapping table MappingTable (variable_id, parent_variable_id, parent_object_id). The downside with this is that, if variables must have a parent, you will then have to enforce a 1:1 relationship between the Variables table and Mappings table.
I would only consider using a mapping table if modelling an n:n relationship, or if there is additional information about the relationship between a variable and it's parent that needs to be recorded.

Table design for hierarchical data

i am trying to design a table which contains sections and each section contains tasks and each task contains sub tasks and so on. I would like to do it under one table. Please let me know the best single table approach which is scalable. I am pretty new to database design. Also please suggest if single table is not the best approach then what could be the best approach to do this. I am using db2.
Put quite simply, I would say use 1 table for tasks.
In addition to all its various other attributes, each task should have a primary identifier, and another column to optionally contain the identifier of its parent task.
If you are using DB2 for z/OS, then you will use a recursive query with a common table expression. Otherwise you you can use a hierarchical recursive query in DB2 for i, or possibly in DB2 for LUW (Linux, Unix, Windows).
Other designs requiring more tables, each specializing in a certain part of the task:subtask relationship, may needlessly introduce issues or limitations.
There are a few ways to do this.
One idea is to use two tables: Sections and Tasks
There could be a one to many relationship between the two. The Task table could be designed as a tree with a TaskId and a ParentTaksId which means you can have Tasks that go n-levels deep (sub tasks of sub tasks og sub tasks etc). Every Task except for the root task will have a parent.
I guess you can also solve this by using a single table where you just add a section column to the Task table I described above.
If you are going to put everything into one table although convenient will be inefficient in the long run. This would mean you will be storing unnecessary repeated groups of data in your database which would not be processor and memory friendly at all. It would in fact violate the Normalization rules and to be more specific the 1st Normal Form which says that there should be no repeating groups that could be found in your table. And it would actually also violate the 3rd Normal Form which means there will be no (transitional) dependency of a non-primary key to another non-primary key.
To give you an illustration, I will put your design into one table. Although I will be guessing on the possible fields but just bear with it because this is for the sake of discussion. Look at the graphics below:
If you look the graphics above (although this is rather small you could download the image and see it closer for yourself), the SectionName, Taskname, TaskInitiator, TaskStartDate and TaskEndDate are unnecessary repeated which as I mentioned earlier a violation of the 1st Normal Form.
Secondly, Taskname, TaskInitiator, TaskStartDate and TaskEndDate are functionally dependent on TaskID which is not a primary key instead of SectionID which in this case should be the primary key (if on a separate table). This is violation of 3rd Normal Form which says that there should be no Transitional Dependence or non-primary key should be dependent on
another non-primary key.
Although there are instances that you have to de-normalized but I believe this one should be normalized. In my own estimation there should be three tables involved in your design, namely, Sections,Tasks and SubTasks that would like the one below.
Section is related to Tasks, that is, a section could have many Tasks.
And Task is related to Sub-Tasks, that is, a Task could have many Sub-tasks.
If I understand correctly the original poster does not know, how many levels of hierarchy will be needed (hence "and so on"). His problem is to create a design that can hold a structure of any depth.
Imho that is a complex issue that does not have a single answer. When implementing such a design you need to count such factors as:
Will the structure be fairly constant? (How many writes?)
How often will this structure be read?
What operations will need to be possible? (Get all children objects of a given object? Get the parent object? Get the direct children?)
If the structure will be constant You could use the nested set model (http://en.wikipedia.org/wiki/Nested_set_model)
In this way the table has a 'left' and 'right' column. The parent object has its left and right column encompasing the values of any of its children object.
In that way you can list all the children of an object using a query like this:
SELECT child.id
FROM table AS parent
JOIN table AS child
ON child.left BETWEEN parent.left AND parent.right
AND child.right BETWEEN parent.left AND parent.right
WHERE
parent.id = #searchId
This design can be VERY fast to read, but is also EXTREMELY costly when the structure changes (for example when adding a child to any object You will have to update any object with a 'right' value that is higher than the inserted one).
If you need to be able to make changes to structure in real time you should probably use a design with two tables - one holding the objects, the second the structure (something like parentId, childId, differenceInHierarchyLevels).

How to Create a Hierarchy in SSAS when duplicate attributes exist at the Root

I have a Dimensional table structure which resembles the following:
Ideally the hierarchial representation should be
CodeClassDesc --> CodeDesc
So A would be a Parent to A and B; B would be a Parent to A, B and C in my Analysis Server Cube. The problem is that because CodeClassDesc has multiple entries in the table it produces multiple duplicate Parents in my Cube with a single corresponding Child Element per Parent which is not what I'd consider a true Hierarchy. Or at least not what I am looking for the expected results.
I believe this is possible in SSAS without having to manipulate the data within the table via a VIEW but I don't know what I'm missing.
I've tried defining the CodeClassDesc and CodeDesc fields as a composite key but that doesn't work, yet I am almost certain there is a way to do this.
After attempting every conceivable permutation of methods to acquire resolution for this, I concluded that normalization of the required attribute was the only way to resolve the issue of having multiple entries of the Parent for every corresponding Child element.
So I created a VIEW of the table using a DISTINCT SELECT of only the CodeClass and CodeClassDesc fields in my DSV (DataSource View) in the Cube. Then I set the CodeClass field as a logical Primary Key and created a relationship between it and the CodeClass field of the main table.
I then used the CodeClassDesc field of the VIEW to create the top-level parent in my Dimension, which gave me only 1 distinct record for each value; and added the CodeDesc fields from the Table to create the Child Relationships. Works like a charm so I guess the answer would have to be that you cannot create a Parent Hierarchy consisting of a single Value per Parent if the source has multiple records.
In the dimension structure, you should change the property KeyColumn of the attribute "CodeClassDesc" to a composite key containing both "CodeClassDesc" and "CodeDesc" then change the NameColumn property to show itself

Many-to-Many but sourced from multiple tables

I am supposed to be shipping out a box with variable contents and tracking this in a database. All of my items (the contents of a box) are different types and require different tables to track their respective pieces of information, although each item type has the same length serial number (i.e. PK are the same datatype). And I have a Boxes table.
So each item has a table (~7 tables) plus the box table. I want to create a BoxContents table. I tried to make a many-to-many relationship intermediate table with two columns: one for BoxID and one for ItemBarcode, where BoxID is a FK to the PK on the Boxes table and the ItemBarcode is a FK to each of the PKs on the Items tables (i.e. I tried to link multiple tables to the same column). Unsurprisingly this didn't work. I tried to insert an item and the FK constraint was violated on all but one of the ItemBarcode relationships.
How can I construct my relationships to link several types of items to one box in one table? Is this a logical approach? Do you need more information?
You need a category hierarchy (aka. class hierarchy, subtype hierarchy, inheritance hierarchy...):
There are 3 main strategies for implementing a category hierarchy. If you choose "all classes in one table" or "class per table", then no matter how many kinds of items you have, you only need one "link" table to implement the many-to-many relationship.
My first choice, if the ItemBarcode values are truly unique, would be to:
EDIT: Added description of required triggers.
Add triggers to enforce the barcode uniqueness.
(An insert/update trigger on each item table needs to verify that all (newly) assigned barcodes do not appear in other item tables.)
Use a single BoxId/ItemBarcode table without a FK relation on the barcode side, but with triggers to ensure it remains valid.
(An insert/update trigger on the association table needs to verify that the barcodes exist in the item tables. A delete trigger on each item table needs to prevent, or cascade, deletion of items that are in the association table. An update trigger on the item tables needs to update and changed barcodes in the association table. This last may be integrated into the insert/update trigger in the prior bullet.)
Consider using a view of all items to access common data by ItemBarcode.
My second choice would be n BoxId/ItemBarcode tables for the n item types. Straightforward, but a bit busy. It makes adding a new item type messier than it needs to be.
I would not use a BoxId/ItemTypeId/ItemBarcode table. It denormalizes the data by associating the ItemTypeId and ItemBarcode again, it doesn't allow the use of a FK on the barcode side, and it still requires triggers to ensure integrity.
Don't be afraid of triggers. There are some problems that they can address quite effectively.
Relational databases are not good with this kind of problem. Your basic design is correct - an association table for FKs between the tables.
Your choices are:
Have multiple columns in your association table - one for for each item table
Merge the item data into one item table
I would go option 2.

Database how to model 1:1 relationship

(VS2008, SqlCE 3.5)
I try to model a 1:1 relationship. So I put the foreign key in the parent table, holding the PK of the child table. Then I set the foreign key to UNIQUE. Still when I create my entity classes (With SqlMetal), the child class has a reference to an EntitySet of the parent, not just a single entity. This seems like a m:1 relation? So what I need to do to make it 1:1 ?
EDIT1:
I'm confused.. Trying to make a set, like this:
StrategySet(ID, EntryStrategyID{Unique}, ExitStrategyID{Unique})
EntryStrategy(ID)
ExitStrategy(ID)
Is this m:1 isn't it? Though it looks like FK's are in the parent, or wouldn't we name StrategySet the parent? And how would I now change this too 1:1 ?
First of all, the parent is table which is referenced by FK from child. So you can't say that your parent table references the child: it's not correct.
Secondly, 1:1 relations can be made through:
Primary Keys in both tables
Primary Key in parent and Unique Foreign Key in child
So in your case, the architecture is correct. I suppose you should check the structure again, and look through this article.
If all columns in EntryStrategy and ExitStrategy are the same, then all you need is simply this (add all other columns too).
If EntryStrategy and ExitStrategy have some different columns, then use this. Keep all common columns in the Strategy table. EntryStrategy and ExitStrategy have only columns specific to each one.
Here is also a generic example of 1:1 due to vertical partitioning of a table.
Before:
After:
Let me understand the situation you are describing.
You have set of fields which make up a "Strategy". A subset of the fields are conceptually the "EntryStrategy" and a non-intersecting subset of the fields are the "ExitStrategy".
In your case a given set of values making up an "EntryStrategy" can be joined with one and only one set of values making up an "ExitStrategy". This is what you mean when you say there is a 1:1 correspondence.
As smirkingman said earlier, in classic relational database modeling, all of these fields belong in a single table because no subset of the fields appear in more than one record.
If you could have multiple ExitStrategies for a single EntryStrategy then you would have two tables with the EntryStrategy being the parent and the ExitStrategies being the children and the ExitStrategy records would have a Foreign Key pointing to the EntryStrategy parent record.
If you could have multiple EntryStrategies for a single ExitStrategy then you would have two tables with the ExitStrategy being the parent and the EntryStrategies being the children and the EntryStrategy records would have a Foreign Key pointing to the ExitStrategy parent record.
If you could have multiple EntryStrategies associated with multiple ExitStrategies then you would have a many-to-many relationship which requires a third table to maintain the correspondences.
The principles of classic database modeling would put all your fields in one table.
As St Woland wrote, you can enforce the 1:1 relationship by having two tables where the foreign key in the child table is a Unique index. But two tables are normally used for 1-to-many relationships.
As Damir wrote, you can enforce the 1:1 relationship by having three tables where the third table has a foreign key to each of the other two tables and both foreign key fields are marked as Unique indices. However, normally you only use three tables in this fashion when you have a many-to-many relationship.
I think you are expecting way too much from the automated data modeling tools to expect them to construct entities that represent your very unconventional approach.
The answer to your main question is simple. How do I represent a 1:1 relationship? You put them in the same record in a single table!