问题
I have table like this below where it save all data with reference id :-
ID Name RefID
A AAAA null
B BBBB A
C CCCC B
D DDDD C
E EEEE D
F FFFF E
Firstly I need some query where I can scan which are the top three reference id level only and show up.
--- Example: When D added below C ---
GLevel ID RefID No
Start A (3)
Level(1) B (A) (2)
Level(2) C (B) (1)
Level(3) D (C)
Result (Down To Top): A,B and C are top three reference id for D Result (Top to Down): A have B,C and D as child based refid
When E has enter below D, then A are not valid reference id for E. I need to show top three reference id for E.
--- Example: When E added below D ---
GLevel Id RefID No
Start A
Level(1) B (A) (3)
Level(2) C (B) (2)
Level(3) D (C) (1)
Level(4) E (D)
Result (Down To Top): D,C and B are top three reference id for E Result (Top to Down): B have C,D and E as child based refid
As a final result I need to rearrange and store my compute view for each ID till Group Level 3 only like below:-
id GroupLevel RefID
A Level(1) B
A Level(2) C
A Level(3) D
B Level(1) C
B Level(2) D
B Level(3) E
C Level(1) D
C Level(2) E
D Level(1) E
E null
Who have cross this problem please help me how to solve it. Anyway thanks on advance for reading this question.
回答1:
Postgreql version (|| instead of '+' for concatenation and quoted level alias):
select ID, 'Level(' || cast(level as varchar(255)) || ')', RefID from (
select t0.ID,
case level.level
when 1 then t1.ID
when 2 then t2.ID
when 3 then t3.ID
end RefID,
level.level
from Test t0
left outer join Test t1 on t1.RefID = t0.ID
left outer join Test t2 on t2.RefID = t1.ID
left outer join Test t3 on t3.RefID = t2.ID
cross join (
select 1 "level" union all
select 2 union all
select 3
) level
) t
where t.RefID is not null
回答2:
create table Test(
ID varchar(10),
Name varchar(10),
RefID varchar(10)
)
insert into Test
select 'A','AAAA',null union all
select 'B','BBBB','A' union all
select 'C','CCCC','B' union all
select 'D','DDDD','C' union all
select 'E','EEEE','D' --union all
--select 'F','FFFF','E'
select ID, 'Level(' + cast(level as varchar(255)) + ')' GroupLevel, RefID from (
select t0.ID,
case level.level
when 1 then t1.ID
when 2 then t2.ID
when 3 then t3.ID
end RefID,
level.level
from Test t0
left outer join Test t1 on t1.RefID = t0.ID
left outer join Test t2 on t2.RefID = t1.ID
left outer join Test t3 on t3.RefID = t2.ID
cross join (
select 1 level union all
select 2 union all
select 3
) level
) t
where t.RefID is not null
Output:
ID | GroupLevel | RefID |
---+------------+-------+
A | Level(1) | B |
A | Level(2) | C |
A | Level(3) | D |
B | Level(1) | C |
B | Level(2) | D |
B | Level(3) | E |
C | Level(1) | D |
C | Level(2) | E |
D | Level(1) | E |
Not sure that I understand what should happen with F. Also, can't see any logic behind 'E null' row in your desired output
回答3:
Rudolf Yurgenson.
Firstly, thanks you so much for your solution given.
I attach the output from your solution below:-
Result: View Group Level
I saw ID A print twice for B as you can see on my attachment others are perfect generating sequence group level based refid. Do you think because I start key-in others data or we need to change a little bit of query you have make?.
"It's unreadable. – Rudolf Yurgenson"
Ok. Now I need to create query where I can get this result:-
-- Example: When E added below D ---
GLevel Id RefID No
Start A
Level(1) B (A) (3)
Level(2) C (B) (2)
Level(3) D (C) (1)
Level(4) E (D)
When I query like "...... Where ID='D' " I get a result C,B and A where 3 level only can listed. It's same process if i choose ".... Where ID='C' " the result should be show B and A only. Because above A has no data. The result should be different if I choose "...... Where ID='E' " where A are not listed and result should be D,C and B only.
I think using SELECT TOP(3) but still idea not on my head to write it.
回答4:
So, you have reversed task that outputs ancestors.
This is a simple query that returns first three ancestors (first one is a parent and etc.) in columns:
select t0.ID, t1.ID ancestor1, t2.ID ancestor2, t3.ID ancestor3
from Test t0
left outer join Test t1 on t0.RefID = t1.ID
left outer join Test t2 on t1.RefID = t2.ID
left outer join Test t3 on t2.RefID = t3.ID
Result is:
|ID|Ancestor1|Ancestor2|Ancestor3|
+--+---------+---------+---------+
|A |NULL |NULL |NULL |
|B |A |NULL |NULL |
|B1|A |NULL |NULL |
|B2|A |NULL |NULL |
|B4|A |NULL |NULL |
|C |B |A |NULL |
|C1|B |A |NULL |
|D |C |B |A |
|E |D |C |B |
|F |E |D |C |
Modified pivot version:
select ID, level, ancestor from (
select distinct
t0.ID,
case level.level
when 1 then t1.ID
when 2 then t2.ID
when 3 then t3.ID
end ancestor, level
from Test t0
left outer join Test t1 on t0.RefID = t1.ID
left outer join Test t2 on t1.RefID = t2.ID
left outer join Test t3 on t2.RefID = t3.ID
cross join (
select 1 as level union all
select 2 union all
select 3
) level
) t where t.ancestor is not null
order by 1, 2
Result:
ID Level Ancestor
B 1 A
B1 1 A
B2 1 A
B4 1 A
C 1 B
C 2 A
C1 1 B
C1 2 A
D 1 C
D 2 B
D 3 A
E 1 D
E 2 C
E 3 B
F 1 E
F 2 D
F 3 C
来源:https://stackoverflow.com/questions/35171909/how-to-query-top-three-reference-id-only-and-how-i-can-query-until-3-level-group