SQL products contain other - sql

I have a table look like this
Parent Child
10 2
10 3
10 4
10 5
11 2
11 3
as you can see parent 10 also contain parent 11 and thats what I want to display in the table, I want to add to it a row with that data :
Parent Child
10 2
10 3
10 4
10 5
**10 11**
11 2
11 3

You can get parents that "contain" other parents using a self-join and aggregation:
with t as (
select t.*, count(*) over (partition by parent) as num_child
from yourtable
)
select tp2.parent, tp.parent
from t tp join
t tp2
on tp.child = tc2.child and tp.parent <> tp2.parent
group by tp.parent, tp2.parent, tp.num_child
having count(*) = tp.num_child -- all children match
(This version assumes no duplicate rows.)
You can then use insert to add these into the table.
Note: If two parents have the same children, two rows will be inserted.

Related

BOM Explosion with Blanks

I have a simple BOM table that contains a parent and a child column.
Every row contains values. There are no blanks.
To bring that table into a BI-Tool I need to add blank values for the parents, like here shown:
As you can see, if an EntityKay has no parent key, then there should be a blank value.
How would you do that?
Example:
Current State:
Child Parent
4 1
5 1
6 2
7 3
8 3
9 3
Needed Result:
Child Parent
1
2
3
4 1
5 1
6 2
7 3
8 3
9 3
This query provides the missing keys, i.e. the parents, that are no childs are selected with the parent null
select distinct Parent Child, null Parent from bom
where Parent not in (select Child from bom)
order by 1;
CHILD PARENT
---------- ------
1
2
3
You must add those records (with an INSERT) to your table and probably update additionaly the description.
insert into bom (Child, Parent)
select distinct Parent Child, null Parent from bom
where Parent not in (select Child from bom)
Result
select * from bom;
CHILD PARENT
---------- ----------
4 1
5 1
6 2
7 3
8 3
9 3
2
3
1
To get the extended data without modifying the table use an UNION ALL of the ofiginal table with the query providing the missing part.
You may add also the names for the new rows using the DECODE as show below in the example
select
Child, Parent, name
from BOM union all
select distinct
Parent Child, null Parent,
decode(Parent,1,'North America',2,'Europa',3,'Asia')
from bom
where Parent not in (select Child from bom)

Oracle SQL Count grouped rows in table

I was wonder if it is possible preferably using a select statement on PL/SQL V11 to get the following results from this table:
Area Store Product
10 1 A
10 1 B
11 1 E
11 1 D
10 2 C
10 2 B
10 2 A
10 3 B
10 3 A
13 1 B
13 1 A
and Return this result, so it groups by Area, and Store and looks for and area and store with the same products. So Area 10 Store 1 has products A and B so it will look at the list for other stores that only have A and B and count them. In this example it counts Area 10 store 1/Area 10 store 3/Area 13 Store 1.
Product Count of groups
AB 3
ABC 1
DE 1
Thanks in advance for the help.
Yes, you can use listagg() and then another group by:
select products, count(*)
from (select listagg(product) within group (order by product) as products
from t
group by area, store
) p
group by products;

Postgresql query to get sum of tree

Hi guys I would like to ask about postgresql and what could be the best query to get sum of column when you have table of elements that has some descendants of more levels ie.
id id_parentvalue
1 null 3
2 null 4
3 1 2
4 2 3
5 3 4
6 3 2
7 4 5
8 4 7
so the result would be rows with sum of all of their tree as follows
value of ids 5 and 6 together is 6 plus value of their parent would be 8 plus his parent would be 11, and same for items with id 7 and 8 so the grandĖ‡parent with id=2 would have value 19
id id_parentvalue
1 null 11
2 null 19
thanks in advance
Use recursive CTEs:
with recursive cte as (
select t.id, t.value, ultimate_parent as id
from t
where id_parent is null
union all
select t.id, t.value, cte.ultimate_parent
from cte join
t
on t.id_parent = cte.id
)
select ultimate_parent, sum(value)
from cte
group by ultimate_parent;
The recursive part starts with the ultimate parents -- the records whose parent is NULL. It then brings in lower levels, step-by-step, keeping the id of the ultimate parent.
The final aggregation just sums the values together.

How to select parent child till end using root parent id in sql?

Below the table :
I need to get without recursion, but use any other join and union.
Id ParentId
1 0
2 1
3 2
4 2
5 4
6 5
7 6
8 7
9 8
N N
Without recursion use any other join queries
DECLARE #Nvalue INT = 10
SELECT NUMBER AS ID,NUMBER-1 AS ParentID FROM (
SELECT DISTINCT NUMBER FROM master..spt_values WHERE number BETWEEN 1 AND #Nvalue
)T

Parent and child relationship is broken when do the sort based on parent name

I want to sort the name based on 1st level (sort only applicable root id is null or level ==1). If I search based on name the result set is broken the parent and child relationship.
I have 500 000 records. What is the best way to do this performance wise?
ID PARENT ID ROOT ID NAME level
===============================================
1 NULL NULL FIRST 1
2 1 1 SECOND 2
3 2 1 THIRD 3
4 1 1 FORTH 4
5 4 1 FIFTH 5
6 NULL NULL SIXTH 1
7 6 6 SEVENTH 2
8 7 6 EIGHTH 2
9 NULL NULL NINTH 1
10 NULL NULL TENTH 1
11 NULL NULL ELEVEN 1
12 11 11 TWELVE 2
13 12 11 THIRTEEN 3
14 13 11 FOURTEEN 4
EXPECTED OUTPUT - SORT BY NAME ASC
ID PARENT ID ROOT ID NAME level
===============================================
11 NULL NULL ELEVEN 1
12 11 11 TWELVE 2
13 12 11 THIRTEEN 3
14 13 11 FOURTEEN 4
1 NULL NULL FIRST 1
2 1 1 SECOND 2
3 2 1 THIRD 3
4 1 1 FORTH 4
5 4 1 FIFTH 5
9 NULL NULL NINTH 1
6 NULL NULL SIXTH 1
7 6 6 SEVENTH 2
8 7 6 EIGHTH 2
10 NULL NULL TENTH 1
It appears that you want to sort the results by two keys:
first, by the NAME column of the root row associated with each row, which may be that row itself, and
second, by the level column.
You can achieve this by joining the table to itself to make the root-NAME association. For example,
select a.*
from
my_table a
join my_table b
on isnull(a.[root id], a.id) = b.id
order by b.name, a.level
Notice the isnull() -- although you generally want to join based on b.id = a.[root id], you need to avoid excluding the root rows, whose root_id is NULL. With the isnull(), you join those rows based on id instead (i.e. you join them to themselves).
You can use a LEFT JOIN to get the parent's name, then use the parent's name to ORDER:
SELECT t1.ID, t1.[PARENT ID], t1.[ROOT ID], t1.NAME, t1.level
FROM mytable AS t1
LEFT JOIN mytable AS t2 ON t2.ID = t1.[ROOT ID]
ORDER BY COALESCE(t2.NAME, t1.NAME), t1.level
If the parent's name is not available, then this is a case of the current row being the parent itself. Hence the row's NAME field is used instead so as to sort.
Finally, records that belong to the same parent are sorted by level.
This should give you what I think you're looking for:
SELECT
id,
parent_id,
root_id,
name,
level
FROM
Your_Table T1
INNER JOIN Your_Table T2 ON T2.id = T1.root_id
ORDER BY
T2.name,
T1.level