I want to fetch a multi-level hierarchy in a sequential manner. I have a table BOMHierarchy in which I have this sample data:
Parent
Child
Parent1
Child1
Parent1
child2
Child1
Child3
Child1
Child4
Child3
Child5
Child3
Child6
I want to show the above data like below in proper hierarchical manner:
Parent
Child
Parent1
Child1
Child1
Child3
Child3
Child5
Child3
Child6
Child1
Child4
Parent1
Child2
I am stuck at fetching this sequential data according to the hierarchy. Can anyone please provide a solution?
I have tried using a CTE and while loop but I'm not getting the required result.
Looks like a classic problem of how to recursively scan a tree. In SQL is simple, what you just need is to create the right ORDER BY.
Try something like this
DECLARE #BOM table (Parent varchar(20), Child varchar(20))
INSERT INTO #BOM(Parent, Child)
VALUES ('Parent1', 'Child1'),
('Parent1', 'Child2'),
('Child1', 'Child3'), ('Child1', 'Child4'),
('Child3', 'Child5'), ('Child3', 'Child6')
-- find all possible combinations recursively
;WITH cte AS
(
SELECT
Parent, Child,
CONVERT(VARCHAR(MAX),Parent + '|' + Child) Chain
FROM
#BOM root
WHERE
NOT EXISTS (SELECT 1
FROM #BOM NotRoot
WHERE root.Parent = NotRoot.Child)
UNION ALL
SELECT
BOM.Parent, BOM.Child, cte.Chain + '|' + CONVERT(VARCHAR(MAX), BOM.Child) Chain
FROM
cte
INNER JOIN
#BOM BOM ON cte.Child = BOM.Parent
)
SELECT
Parent, Child
FROM
cte
ORDER BY
Chain
Related
I have 2 tables
a table of PARENT ACCOUNTS (holds PARENT ID and CHILD ID)
a table of CHILD ACCOUNTS (Holds CHILD ID and ATTRIBUTE)
1 PARENT can have many CHILDREN
Each Child has one or more attributes, and each child must have the same as the other in the parent group
so if Parent 1 has Child1, Child2, Child3
Child1, Child2, Child3 MUST have the same attribute - say they are BLUE
If Child3 is missing this attribute (doesn't exist) then I need to show All the Child accounts and highlight which one is the missing one.
select Child, Parent,Attribute
from
[dbo].[AttributeTable] as AttReq
LEFT OUTER JOIN
[dbo].[ChildDetails] ChildDetails
ON AttReq.Child = ChildDetails.Child
where Parent = 'Parent1'
CHILD ACOUNT
PARENT ACCOUNT
ATTRIBUTE
Child1
Parent1
Attribute 1
Child1
Parent1
Attribute 2
Child1
Parent1
Attribute 3
Child2
Parent1
Attribute 1
Child2
Parent1
Attribute 4
Child2
Parent1
Attribute 2
Child2
Parent1
Attribute 3
Child3
Parent1
Attribute 1
Child3
Parent1
Attribute 2
Child3
Parent1
Attribute 3
So this one, only Child 2 has attribute 4.
I want to list all the Child accounts that are missing 4 - and which one HAS 4. I don't need to show which ones they all have.
CHILD ACOUNT
PARENT ACCOUNT
ATTRIBUTE
Child1
Parent1
Missing Attribute 4
Child2
Parent1
Missing Attribute 4
Child3
Parent1
Has Attribute 4
If you are evaluating the instances of an attribute across several attributes, you need a sub-query to evaluate at a higher level of analysis.
I would probably do this with a case statement that sums the instances of the attribute you are looking for across each child.
To take your query as the sub-query:
SELECT SUM(CASE WHEN ATTRIBUTE = 'Attribute 4' THEN 1 ELSE 0 END) [Attribute Count]
,Child
,Parent
FROM(
SELECT Child
,Parent
,Attribute
FROM [dbo].[AttributeTable] as AttReq
LEFT OUTER JOIN [dbo].[ChildDetails] ChildDetails
ON AttReq.Child = ChildDetails.Child
WHERE Parent = 'Parent1'
) Subquery
GROUP BY Child
,Parent
A child with [Attribute Count] more than 0 have the attribute. Those with 0 do not have the attribute.
I should get root element with all descendants from that structure:
rootA
rootB
child1
rootC
child2
chold3
rootD
child4
RESULT:
Root| Child
rootA child1
rootA child2
rootA child3
rootD child4
I understand, that firstly I should get root elements without parents:
SELECT DISTINCT
rootId,
childId
FROM
root
WHERE rootId IS NULL
But I dont know the next step.
Do you have some variants?
Thanks!
This is done with a Common Table Expression (CTE):
;WITH cte_hierarchy AS (
-- get all roots
SELECT DISTINCT
rootId, childId
FROM
root
WHERE rootId IS NULL
UNION ALL
-- this is the recursive part
-- get all children for all roots, including children of children, etc.
SELECT
child.rootId, child.childId
FROM root child
JOIN cte_hierarchy parent ON parent.childid=child.rootid
)
SELECT * FROM cte_hierarchy;
In Parse you can select or include a key from a pointer. Select key Parent.child.id
Is it possible to do the same in SQL if you have child indexed to parent?
SELECT Parent.child.id
In SQL you do this:
Select * from parent, child where parent.id = child.id;
I am searching parents according to child properties
I have this view returning parent and child information, I cannot change the view definition because I need to provide the child info for filtering.
Since different children can be related to the same parents, I don't get distinct results
How can I force SQL to return single parent results by using the first child found?
For example:
parent1 foo1 child1 data a
parent1 foo1 child3 data a
parent2 foo2 child1 data a
parent2 foo2 child3 data a
parent2 foo2 child4 data a
What I would be happy to get is:
parent1 foo1 child1 data a
parent2 foo2 child1 data a
Sample scripts:
drop table relations;
CREATE TABLE relations(
parent_id nchar(10) NULL,
child_id nchar(10) NULL
)
drop table items;
CREATE TABLE items(
item_id nchar(10) NULL,
data nchar(10) NULL
);
insert into items values('parent1', 'data x');
insert into items values('parent2', 'data y');
insert into items values('child1', 'data a');
insert into items values('child2', 'data b');
insert into items values('child3', 'data a');
insert into items values('child4', 'data a');
insert into relations values('parent1', 'child1');
insert into relations values('parent1', 'child3');
insert into relations values('parent2', 'child1');
insert into relations values('parent2', 'child2');
insert into relations values('parent2', 'child3');
insert into relations values('parent2', 'child4');
drop view v_parent_child;
create view v_parent_child as
select rel.parent_id,parent.data as parent_data ,rel.child_id, child.data as child_data
from relations as rel
join items as parent on rel.parent_id = parent.item_id
join items as child on rel.child_id = child.item_id
;
select * from v_parent_child where child_data = 'data a';
you can do row over partition in the join.
select parent_id, parent_data , child_id, child_data from (
select *,
row_number() over (partition by parent_id order by parent_id) as rn
FROM v_parent_child) t
where t.rn = 1 ;
like here: Oracle 'Partition By' and 'Row_Number' keyword
Try the below view.
create view v_parent_child as
select rel.parent_id,parent.data as parent_data ,rel.child_id, child.data as child_data
from ( select parent_id,
child_id
from
(
select parent_id,
child_id,
row_number() over (partition by parent_id order by child_id) rn
from relations ) oneChild
where rn = 1 ) rel
join items parent on rel.parent_id = parent.item_id
join items child on rel.child_id = child.item_id
I've a table:
Id | Name | ParentID
I want to select records whose parentid not equal to zero, with parent record(parent record have parentid = 0, but some parent record don't have child record I want to skip them )
Try this:
SELECT child.Id,
child.Name,
child.ParentId,
parent.Name as ParentName
FROM your_table child
JOIN your_table parent ON child.ParentId = parent.id;
Check this one:
select * from child c,parent p where c.ID=P.ParentID and c.ParentID !=0