oracle two-way hierarchical query - sql

I have a question about oracle hierarchical query.
Lets say I have relation table for units relating to each other where unit1 is parent and unit2 is child.
ID UNIT1 UNIT2 OTHER COLUMNS
------lots of data--------
Lets assume I am looking at one unit, and now I want full graph/tree abouts its relations with other units.
It is easy to just get the parents ones that are connected to each other and also the child ones:
INSERT INTO search_table
SELECT id
FROM mytable
START WITH unit_id1 = 12 (or any random unit id)
CONNECT BY nocycle PRIOR unit_id2 = unit_id1
GROUP BY id;
This is for moving up and similar is for moving down. Now what happens is that when for example moving up 1 step, it does not search for that units child units, but only keeps searching for parents. So basically I if parent unit has another child (not the one we are looking) I wont be able to reach it, because the syntax keeps only looking for parents. And later it looks only for children but not these two combined.
Is there a way that for each child or parent unit, I could search for both parents and children?

I'm not sure you can do it with a single query.
But you can easily do it in two steps :
find the older ancestor A of your unit(the one who doesn't have parents)
find all the children of A

Related

Required Oracle Query to populate Hierarchies

Background...
As part of existing data conversion we need to convert to populate Adhoc Hierarchies with a limited information.
Currently we have a finger countable members from CXO House treated to be users of this Adhoc Hierarchies.
They have their choice of Employee Hierarchical combinations for a purpose.
These hierarchies have only Parent - Child relation and can be of at any level to any level of Org Hierarchy.
In the other words... child never become a parent unless he has subordinates for him.
We have an employee table of ORG EmpHierarchy (OH) that has Organizational hierarchies.
But, which can't be directly used but we can take help of these columns to form our logic. This table is no way related to current model.
We have a few other tables HeadofDepartment(HOD), HierarchyDetails(HD) and a Stage Table same as HD.
OrgEmpHierarchy (OH) Has:
OH_ID - Organizational HierarchyID (DB Sequence)
OH_PID - (Parent ID) one of the values from previous column.
OH_EmpID - Organizational EmpID.
HeadofDepartment (HOD) Has:
HOD_ID - Head of Dept. ID (DB Sequence)
HOD_EmpID - Organizational EmpID.
HierarchyDetails (HD) Has:
HD_ID - Hierarchy Details ID (DB Sequence)
HD_PID - (ParentID) of of the values from previous column.
HD_HOD_ID - (Foreign Key) HOD_ID from HOD.
HD_EmpID - Organizational EmpID.
We need to populate the Hierarchy for each HOD_ID from Head of Department (HOD) in Hierarchy Details (HD) table.
We are able to populate values in HD for HD_ID, HD_HOD_ID, HD_Emp_ID. HD_PID is populated with NULL.
Now with the help of OH, HOD I need to populate Hierarchies in HD_PID in HD table.
Can some one give me a Oracle SQL/ PLSQL query which udpates the HD_PID?
Since this is an assignment I am not going to "give you the SQL".
You will need to use a hierarchical query which has the basic format:
SELECT some_columns
FROM a_table
START WITH some_condition
CONNECT BY PRIOR some_column = some_other_column
So, which table to select from? Well, looking at your tables OrgEmpHierarchy has contains a relationship between OH_PID (the Parent ID) and OH_EmpID so you should be using this table and connecting on those columns.
So, what should you start with? Without any data, it is difficult to say but presumably the top of the hierarchy is either an Owner/Director or the Head of Departments - if it is that latter case then you can look at starting with those employees that are IN the HeadofDepartment table.
What to select?
You're using the OH_PID and OH_EmpID columns to connect the query so you can select these as they define the hierarchical relationship.
You can select a sequence using ROWNUM or use an actual sequence YOUR_SEQUENCE.NEXTVAL.
You need to know the Head of Department - assuming you start the hierarchy at with those head of departments then there is a very simple operator that lets you "connect by the root" of the hierarchy - I'm sure a simple web search will inform you of its syntax an usage.
That just about covers it all except you'll want to insert it into a table. So, use:
INSERT INTO HierarchyDetails ( columns )
SELECT ...

Displaying multiple columns on one row (SQL)

I have a report I am trying to make that displays parent information and all children in one household on ONE row.
There is no "parent" table that stores the information on parents and there is no ID that links parents to child and no ID that links sibling to sibling. The only way to tell if they are siblings is if they have the same address (logic being that if they have the same address, they live together, and are part of the same household). All the information is pulled from a "student" table or a custom field in the student table that stores the parent information, address they live at, etc.
Instead of displaying parent info twice I want to display
the information like this:
Parent_name, address, phone,child1_name, child1_schoolname, child1_age, child2_name, child2_schoolname, child2_age, etc(for every child in that household)
The problem is that not every household will have the same amount of children and I can only link siblings by their address.
How can I display all information for each household on ONE row? Is this possible and how? I've tried pivot table but with no avail.
This is a classic 'you shouldn't be doing reports in the database' question. A database is for data retrieval, not data formatting. But let's assume you know this and need to do it anyway for some reason.
The algorithm I'd use for this would be
Create some windowed queries across the data; group by address (the joinable value) and sort by age desc.
Create a query that utilize this window and returns the first item in each group.
Create additional queries that return the second, the third, the fourth, in each group. etc.
Outer join these together.
This is going to be far easier if you define some maximum number of siblings (five?) as opposed to dynamically building these siblings.
If the parents are in the same table, how do you know which items are parents and which are children?
In case you have two tables one for Parent(first table) and one for Children(second table) as below:
You can do something like that in your data model:
select Parent.NAME as parent_name,
Parent.ADDRESS as parent_address,
Parent.PHONE AS phone,
(
select listagg(Child.NAME,',')
within group(order by Child.NAME)
from CHILD Child
where Child.ADDRESS=Parent.ADDRESS
)as children_names,
(
select
listagg(Child.AGE,',')
within group(order by Child.NAME)
from CHILD Child
where Child.ADDRESS=Parent.ADDRESS
)as children_ages
from PARENT Parent .
And you will have the output query result:
Listagg is your solution which operates as you want bringing muliple rows in one.
However,listagg is compatible for database 11g and newest versions,
so in case you have older version,this is not going to work.
Hope this help.

How to copy an entity tree in database

I have a pretty standard relational data situation in which there is a root entity (and corresponding table) with children entities. These children have children entities and so on and so forth for about 6 levels. Each level has a many children to one parent relationship. I would like to write a procedure that effectively copies the root entity and all of its children entities (recursively copying the childrens' children), creating new entities for each along the way while storing each in its respective table.
I know this could be done with nested cursors, but I don't want to do it that way. I know that there is a more elegant solution out there I just need help creating it. I have a feeling that the solution lies in a combination of OUTPUT clauses and MERGE statements.
If you could, please tailor your answer to the novice SQL developer level. I will need an explanation or a link to an explanation for any structure you use that is outside of the basic SELECT INSERT UPDATE and DELETE.
Thank you for your time.
You need to use common table expression. Check this:
http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/
I'll assume that you want to copy a subset of the data that is in a hierarchy of tables. By hierarchy I mean tables that are interrelated through foreign keys in the obvious sense of the word. For example, Customers would be a root table, Orders a child of it and OrderDetails another child (at the 3rd level).
First we copy the root table of the hierarchy:
MERGE RootTable as target
USING (
SELECT *
FROM RootTable
WHERE SomeCondition
) AS src
ON 1=2 -- this is so that all rows that do not match will be added
WHEN NOT MATCHED THEN INSERT (AllColumns) VALUES (AllColumns)
OUTPUT src.ID as OldID, INSERTED.ID as NewID INTO #RootTableMapping
Now we have a 1 to 1 mapping of the copy source and copy target IDs of the root table in #RootTableMapping. Also, all root rows were copied.
We now need to copy all child tables. Here's the statement for one:
MERGE ChildTable as target
USING (
SELECT *, #RootTableMapping.NewID AS NewParentID
FROM ChildTable
JOIN #RootTableMapping ON ChildTable.RootID = #RootTableMapping.OldID
WHERE SomeCondition
) AS src
WHEN NOT MATCHED THEN INSERT (AllColumns, RootID) VALUES (AllColumns, NewParentID)
Here, we obtain for each child row the ID of the cloned root table row so that we can link up the hierarchy. For that we use #RootTableMapping. We copy all columns unmodified, except for the ID of the parent which we substitute with the NewID from the mapping.
You'd need one such MERGE statement for each child table. The concept also extends to hierarchies with more than 2 levels by adding additional joins. All levels except for the bottom level must record the mapping of copy-source IDs to copy-target IDs to allow the next layer below to obtain the new IDs.
Feel free to ask further questions in case I did not make everything clear enough. I know this is a rough sketch.

Parent Child Relationships Between Measure Groups in SSAS

I am having a tough time figuring out how I am supposed to implement parent-child relationships between my measure groups in SSAS. Essentially I am just trying recreate a standard SQL join so that I can lookup measures in my Parent group while using keys in my Child group.
For example, let's say I have the following dimensions:
Parent
Child (FK: ParentID)
Time
And I have the following measure groups
ParentFact (Keys: ParentID, TimeID - Measures Related to the parent over time)
ChildFact (Keys: ChildID, TimeID - Measures related to the child over time)
I have not created any specific dimensions for any of my fact tables.
In the end I just want to run a query like this to list out measures in my Child table joined to measures in my Parent table:
SELECT
{
[ChildMeasure]
, [ParentMeasure]
} ON COLUMNS
, [Child].Children ON ROWS
FROM
[MyCube]
WHERE
[Time].[100]
When this query runs, the Child rows are correctly listed, alongside the appropriate measure values for Time ID 100. Unfortunately, ParentMeasure is all the same, and appears to be an aggregate for this value over all Parents at Time ID 100. I would expect this column to show the value from each child's associated parent at Time ID 100.
What am I doing wrong here? Do I need to create FactDimensions for each FactTable, and somehow relate those? Should I crate an association between Parent and Child in my Datasource view? Would that make it a Snowflake schema, which I think I am supposed to avoid?
As a side note, my ChildFact table actually contains ParentID as one of the measures, because it is on the relational table in the datasource (probably due to some previous denormalization effort by the DB developer). Should I remove any measures that are actually FKs in my fact table, or is that somehow required for what I am trying to do?
I don't think you should attempt to create a single Fact table due to the obvious granularity issue.
I think you should add a Dimension Relationship in your Cube definition, between your Child Fact and Parent Dimension, using the existing FK column.
Probably the only valid use of ParentID as a Measure would be to get a Distinct Count.
There is no need to create two facts here.
Create a single Fact table (ParentID, ChildID, TimeID)
Create 3 dimension DimParent, DimChild, DimTime
FK of Fact table will refer to respective dimension table
Also, check the Attribute relationship how Facts are sliced with dimension

SQL x-ref query to return a single row of a variable number of records

I have a table of parents (real mom & dad parent names in a table), a table of children (these are children of the parents, first and last name) and an x-ref table: xref-id, parent-id and child-id.
The xref table is to accommodate the variable number of children a mom/dad combo could have.
I need a query to return a single row of parents and children names. The problem I am facing is some parents have 1 child, some have more than 1 child.
I'm quite stumped...
TLB_PARENT:
p_id, momfname, dadfname
TLB_CHILD:
c_id, childfname, childlname
TLB_XREF
xref_id, p_id, c_id
Any help is really appreciated!
The number of culmns is a SQL Query is not dynamic, it's very firmly fixed.
The closest you can get is deciding on a maximum number of children. You'll then have blanks in many cells, but more importantly, the possibility that the table gets filled and some children don't get displayed.
How to do this depends on the version of SQL you have.
Also, note that you can have this scenario in real life...
WomanA and ManA have ChildA
WomanA and ManB have ChildB
WomanB and ManB have ChildC
WomanB and ManA have ChildD
Although that's a bit of a messy world, I know some really really messy families. I'm just pointing out that your simplification is likely to have issues in any decent sized real world population.