The idea that inspired me in trying to find a solution is to create a second table (Temp_Cable_Table) in order to proceed by successive steps.
The problem you raise seems to me difficult to implement because it looks more like a procedure than a data selection query. Therefore, consider my work as a suggestion rather than a solution.
On the first pass the Temp_Cable_Table is filled with the split of the Cable_Codes fields of Cable_Table.
Cable_table
Cable_Source Cable_Codes
------------------- -----------
BL1 DD1,ED1,BL2
BL2 CD1,DD1,ED1,BL3,BL4
BL3 CD1,ED1
BL4 ED1
Temp_Cable_table
Cable_Source Cable_Codes
------------------- ------------------
BL1 DD1
BL1 ED1
BL1 BL2
BL2 CD1
BL2 DD1
BL2 ED1
BL2 BL3
BL2 BL4
BL3 CD1
BL3 ED1
BL4 ED1
The Temp_Cable_Table is then updated by propagating the BL1 code to all the remaining lines having the same Cable_Codes as the lines with Cable_Source equal to 'BL1'. or to all lines with different Cable_Source but equal Cable_Codes.
Step 3 therefore eliminates any duplicate rows that may have been generated in step 2.
Finally, step 4 collapses all rows of Temp_Codes_Table into one row by aggregating the Cable_Codes fields.
Who knows if all this will be useful!
--
-- Step 0
--
if object_id('Temp_Cable_Table') is not null drop table Temp_Cable_Table
if object_id('Cable_Table') is not null drop table Cable_Table
create table Cable_Table
(
Cable_Source varchar(3)
, Cable_Codes varchar(200)
)
insert into Cable_Table (Cable_Source,Cable_Codes) values
('BL1', 'DD1,ED1,BL2')
, ('BL2', 'CD1,DD1,ED1,BL3,BL4')
, ('BL3', 'CD1,ED1'), ('BL4','ED1')
create table Temp_Cable_Table
(
Cable_Source varchar(3)
, Cable_Codes varchar(200)
)
--
-- Step 1
--
insert into
Temp_Cable_Table
(
Cable_Source
, Cable_Codes
)
select
Cable_Source
, value
from
Cable_Table
cross apply
string_split(Cable_Codes, ',')
order by
Cable_Source
--
-- Step 2
--
update
Temp_Cable_Table
set
Cable_Source = 'BL1'
from
Temp_Cable_Table t
where
t.Cable_Source not in ('BL1')
and
(
exists
(
select
1
from
Temp_Cable_Table tt
where
tt.Cable_Source = 'BL1'
and tt.Cable_Codes = t.Cable_Codes
)
or
exists
(
select
1
from
Temp_Cable_Table tt
where
tt.Cable_Source <> T.Cable_Source
and tt.Cable_Codes = t.Cable_Source
)
)
--
-- Step 3
--
;with cte as
(
select
t.*
, row_number() over (partition by Cable_Codes order by t.Cable_Codes) as rn
from
Temp_Cable_Table t
)
delete
cte
where
rn > 1
---
-- Step 4
--
select
Cable_Source
, string_agg (convert(varchar(max),Cable_Codes), ',')
from
Temp_Cable_Table
group by Cable_Source