Author |
Topic |
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-16 : 10:42:56
|
Is there a way to write a select statement to get an indented BOM? One table: BMPRDSTRParent_Item Component_Item Qty_Per A1 C1 3 A1 C2 2 C1 D1 1 C1 D2 4 If I query parent A1 I would want the following:Level Comp Qty1 C1 32 D1 12 D2 41 C2 3 |
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 10:57:17
|
Question: How deep can the BOM go?If there is a fixed max depth, you can do it as a sequence of self-joins. If the max depth is not fixed, you can use a recursive CTE to do it.BTW I don't seen any indentation on your sample output. |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-16 : 11:01:17
|
11 levels deep |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 11:07:46
|
I'd go with a series of self-joins unless the table is small. It looks ugly but performs much better than a recursive CTE |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 12:16:16
|
e.g. worked out to four levelsdeclare @ table (Parent_Item char(2), Component_Item char(2), Qty_Per int)insert into @ (Parent_Item, Component_Item, Qty_Per) values--Parent_Item Component_Item Qty_Per ('A1', 'C1', 3), ('A1', 'C2', 2), ('C1', 'D1', 1), ('C1', 'D2', 4)select bom.[Level], bom.Comp, bom.Qtyfrom ( select distinct bom.* from @ _0 left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty from @) _1 on _0.Component_Item = _1.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty from @) _2 on _1.Comp = _2.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty from @) _3 on _2.Comp = _3.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty from @) _4 on _3.Comp = _4.Parent_Item cross apply ( select distinct * from ( select 1 as [Level], _0.Component_Item as Comp, _0.Qty_Per as Qty, _0.Component_Item as OrderOn union all select 2, _1.Comp, _1.Qty, _0.Component_Item + _1.Comp union all select 3, _2.Comp, _2.Qty, _0.Component_Item + _1.Comp + _2.Comp union all select 4, _3.Comp, _3.Qty, _0.Component_Item + _1.Comp + _2.Comp + _3.Comp union all select 5, _4.Comp, _4.Qty, _0.Component_Item + _1.Comp + _2.Comp + _3.Comp + _4.Comp ) bom ) bom where _0.Parent_Item = 'A1' and bom.Comp is not null) bomorder By bom.OrderOn |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-16 : 15:06:02
|
The above is working, thanks for that. There is a seq_no that I did not include in the original post. any way to sort by that? So the level one items will have seq_no's of 10, 20 , 30 , 40which tells the order they should show. Each level under will have the same seq_no. I tried this, but it puts all level 2select bom.[Level], bom.Comp, bom.Qty, bom.seq_nofrom ( select distinct bom.* from bmprdstr_sql _0 left join (select item_no,seq_no, comp_item_no as Comp, qty_per_par as Qty from bmprdstr_sql) _1 on _0.comp_item_no = _1.item_no left join (select item_no,seq_no, comp_item_no as Comp, qty_per_par as Qty from bmprdstr_sql) _2 on _1.Comp = _2.item_no left join (select item_no,seq_no, comp_item_no as Comp, qty_per_par as Qty from bmprdstr_sql) _3 on _2.Comp = _3.item_no left join (select item_no,seq_no, comp_item_no as Comp, qty_per_par as Qty from bmprdstr_sql) _4 on _3.Comp = _4.item_no cross apply ( select distinct * from ( select 1 as [Level],_0.seq_no, _0.comp_item_no as Comp, _0.qty_per_par as Qty, _0.comp_item_no as OrderOn union all select 2,_1.seq_no, _1.Comp, _1.Qty, _0.comp_item_no + _1.Comp union all select 3,_2.seq_no, _2.Comp, _2.Qty, _0.comp_item_no + _1.Comp + _2.Comp union all select 4, _3.seq_no, _3.Comp, _3.Qty, _0.comp_item_no + _1.Comp + _2.Comp + _3.Comp union all select 5,_4.seq_no, _4.Comp, _4.Qty, _0.comp_item_no + _1.Comp + _2.Comp + _3.Comp + _4.Comp ) bom ) bom where _0.item_no = '56141' and bom.Comp is not null) bomorder By OrderOn,seq_no |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 15:17:25
|
Please post your revised data |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 15:45:14
|
I mean your revised input data with the SeqNo column |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-16 : 15:45:20
|
[code]Parent_Item Component_Item Qty_Per SEQ_no A1 C1 3 10 A1 C2 2 20 A1 C3 3 30 C1 D1 1 10 C1 D2 4 20D1 and D2 should still fall under C1[/code] |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-16 : 15:47:33
|
[code]Level Comp Qty1 C1 32 D1 12 D2 41 C2 31 C3 3[/code] |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 15:56:30
|
OK -- so with the new column, I have this:declare @ table (Parent_Item char(2), Component_Item char(2), Qty_Per int, SeqNo Int)insert into @ (Parent_Item, Component_Item, Qty_Per, SeqNo) values-- Parent_Item Component_Item Qty_Per SEQ_no ('A1','C1',3,10),('A1','C2',2,20),('A1','C3',3,30),('C1','D1',1,10),('C1','D2',4,20)select bom.[Level], bom.Comp, bom.Qty, bom.SeqNofrom ( select distinct bom.* from @ _0 left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _1 on _0.Component_Item = _1.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _2 on _1.Comp = _2.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _3 on _2.Comp = _3.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _4 on _3.Comp = _4.Parent_Item cross apply ( select distinct * from ( select 1 as [Level], _0.Component_Item as Comp, _0.Qty_Per as Qty, _0.SeqNo, _0.Component_Item as OrderBY union all select 2, _1.Comp, _1.Qty, _1.SeqNo, _0.Component_Item + _1.Comp union all select 3, _2.Comp, _2.Qty, _2.SeqNo, _0.Component_Item + _1.Comp + _2.Comp union all select 4, _3.Comp, _3.Qty, _3.SeqNo, _0.Component_Item + _1.Comp + _2.Comp + _3.Comp union all select 5, _4.Comp, _4.Qty, _4.SeqNo, _0.Component_Item + _1.Comp + _2.Comp + _3.Comp + _4.Comp ) bom ) bom where _0.Parent_Item = 'A1' and bom.Comp is not null) bomorder By bom.OrderBy, bom.SeqNo which returns this:Level Comp Qty SeqNo1 C1 3 102 D1 1 102 D2 4 201 C2 2 201 C3 3 30 So, what should the correct order be? |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-16 : 16:12:39
|
Still not coming out quite right when I run against the live data. Here is a sample of what I'm getting. Level Comp Qty seq_no1 32285 8.000000 181 34996 1.000000 301 34997 3.000000 281 37905 2.000000 261 55754 1.000000 62 67719 1.000000 21 55755 1.000000 162 67719 1.000000 2 They should be in this order.1 55754 1.000000 62 67719 1.000000 21 55755 1.000000 162 67719 1.000000 2 1 32285 8.000000 181 37905 2.000000 261 34997 3.000000 281 34996 1.000000 30I think if the level 1's are in order by sequence number then the rest will fall into place |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-16 : 16:25:52
|
Try this. Since I don't have live data and the test data set is a little small, I can't test it fully, but I think it's on the right track:declare @ table (Parent_Item char(2), Component_Item char(2), Qty_Per int, SeqNo Int)insert into @ (Parent_Item, Component_Item, Qty_Per, SeqNo) values-- Parent_Item Component_Item Qty_Per SEQ_no ('A1','C1',3,10),('A1','C2',2,20),('A1','C3',3,30),('C1','D1',1,10),('C1','D2',4,20)select bom.[Level], bom.Comp, bom.Qty, bom.SeqNofrom ( select distinct bom.* from @ _0 left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _1 on _0.Component_Item = _1.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _2 on _1.Comp = _2.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _3 on _2.Comp = _3.Parent_Item left join (select Parent_Item, Component_Item as Comp, Qty_Per as Qty, SeqNo from @) _4 on _3.Comp = _4.Parent_Item cross apply ( select cast(_0.SeqNo as char(2)) As _0 , cast(_1.SeqNo as char(2)) As _1 , cast(_2.SeqNo as char(2)) As _2 , cast(_3.SeqNo as char(2)) As _3 , cast(_4.SeqNo as char(2)) As _4 ) seq cross apply ( select distinct * from ( select 1 as [Level], _0.Component_Item as Comp, _0.Qty_Per as Qty, _0.SeqNo, seq._0 + _0.Component_Item as OrderBY union all select 2, _1.Comp, _1.Qty, _1.SeqNo, seq._0 + _0.Component_Item + seq._1 + _1.Comp union all select 3, _2.Comp, _2.Qty, _2.SeqNo, seq._0 + _0.Component_Item + seq._1 + _1.Comp + seq._2 + _2.Comp union all select 4, _3.Comp, _3.Qty, _3.SeqNo, seq._0 + _0.Component_Item + seq._1 + _1.Comp + seq._2 + _2.Comp + seq._3 + _3.Comp union all select 5, _4.Comp, _4.Qty, _4.SeqNo, seq._0 + _0.Component_Item + seq._1 + _1.Comp + seq._2 + _2.Comp + seq._3 + _3.Comp + seq._4 + _4.Comp ) bom ) bom where _0.Parent_Item = 'A1' and bom.Comp is not null) bomorder By bom.OrderBy |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-17 : 12:51:42
|
Still not ordering. Use this data and you should see what I'm seeing. First item listed should be 67805 because it level 1 and has the lowest seqno:declare @ table (Parent_Item char(5), Component_Item char(5), Qty_Per int, SeqNo Int)insert into @ (parent_item, component_item, qty_per, seqno) values('56141','67805',1,4),('67805','30699',1,2),('67805','32885',1,4),('67805','30724',1,6),('56141','55754',1,6),('55754','67719',1,2),('56141','55913',1,8),('55913','67719',1,2),('56141','55761',1,12),('55761','67720',1,2),('56141','32285',1,14),('56141','60579',1,16),('56141','67805',1,4) |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2015-03-17 : 13:08:34
|
Changed the inner cross apply to: cross apply ( select right('00' + cast(_0.SeqNo as varchar(2)), 2) As _0 , right('00' + cast(_1.SeqNo as varchar(2)), 2) As _1 , right('00' + cast(_2.SeqNo as varchar(2)), 2) As _2 , right('00' + cast(_3.SeqNo as varchar(2)), 2) As _3 , right('00' + cast(_4.SeqNo as varchar(2)), 2) As _4 ) seq since the order by is ascii, not numeric |
|
|
Vack
Aged Yak Warrior
530 Posts |
Posted - 2015-03-17 : 13:12:34
|
Who ever you work for, tell them they don't pay you enough money. : )Thanks for your help. |
|
|
huangchen
Starting Member
37 Posts |
Posted - 2015-04-02 : 05:57:01
|
unspammed |
|
|
|
|
|