Reputation: 2119
I met with some weird DB design during a data migration, and trying to convert a table data to a more normalized form.
Here employees belongs to various positions and Employee-Position table looks like: EmpNo, Position1, SalCode1, Position2, SalCode2, Position3, SalCode3, Position4, SalCode4
etc.
EmpNo Position01 SalCodeS01 Position02 SalCodeS02 Position03 SalCodeS03
E123 EL028 ENADV EL029 ENADV BF046 ENADV
E125 EL028 LHENAD EL029 LHENAD BF046 LHENAD
E126 EL049 LHENAD BF046 LHENAD BF047 LHENAD
E127 EL028 LHENAD EL029 LHENAD BF046 LHENAD
E128 EL028 LHENAD EL029 LHENAD BF046 LHENAD
E129 EL049 LHENAD BF046 LHENAD BF047 LHENAD
Trying to normalize like EmpNo, Position, SalCode
EmpNo Position SalCode
E123 EL028 ENADV
E123 EL029 ENADV
E123 BF046 ENADV
E123 BF047 ENADV
E125 EL028 LHENAD
E125 EL029 LHENAD
E125 BF046 LHENAD
E125 BF047 LHENAD
Is anyone can suggest the best method to accomplish this? Is PIVOT possible? Thanks. PS. Please note that I have SELECT permission only and this is one table among 4 tables in a JOIN
Upvotes: 0
Views: 53
Reputation: 93694
CREATE TABLE #temp
(
EmpNo VARCHAR(50),
Position01 VARCHAR(50),
SalCodeS01 VARCHAR(50),
Position02 VARCHAR(50),
SalCodeS02 VARCHAR(50),
Position03 VARCHAR(50),
SalCodeS03 VARCHAR(50)
)
INSERT INTO #temp
(EmpNo,Position01,SalCodeS01,Position02,
SalCodeS02,Position03,SalCodeS03)
VALUES ('E123','EL028','ENADV','EL029',
'ENADV','BF046','ENADV'),
('E125','EL028','LHENAD','EL029',
'LHENAD','BF046','LHENAD'),
('E126','EL049','LHENAD','BF046',
'LHENAD','BF047','LHENAD')
SELECT A.EmpNo,
a.Position,
b.SalCode
FROM (SELECT empno,
Split.a.value('.', 'VARCHAR(100)') Position
FROM (SELECT empno,
Cast ('<M>'
+ Replace(Position01+','+Position02+','+Position03, ',', '</M><M>')
+ '</M>' AS XML) AS Data
FROM #temp) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)) A
JOIN (SELECT empno,
Split.a.value('.', 'VARCHAR(100)') SalCode
FROM (SELECT empno,
Cast ('<M>'
+ Replace(SalCodeS01+','+SalCodeS02+','+SalCodeS03, ',', '</M><M>')
+ '</M>' AS XML) AS Data
FROM #temp) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)) B
ON a.EmpNo = b.EmpNo
OUTPUT
EmpNo Position SalCode
E123 EL028 ENADV
E123 EL029 ENADV
E123 BF046 ENADV
E123 EL028 ENADV
E123 EL029 ENADV
E123 BF046 ENADV
E123 EL028 ENADV
E123 EL029 ENADV
E123 BF046 ENADV
E125 EL028 LHENAD
E125 EL029 LHENAD
E125 BF046 LHENAD
E125 EL028 LHENAD
E125 EL029 LHENAD
E125 BF046 LHENAD
E125 EL028 LHENAD
E125 EL029 LHENAD
E125 BF046 LHENAD
E126 EL049 LHENAD
E126 BF046 LHENAD
E126 BF047 LHENAD
E126 EL049 LHENAD
E126 BF046 LHENAD
.......
Upvotes: 0
Reputation: 2091
I suggest you write a procedure to do this task. Define a cursor and for each iteration of the cursor, do this.
INSERT INTO employee_positions_new (EmpNo, Position01, SalCodeS01);
INSERT INTO employee_positions_new (EmpNo, Position02, SalCodeS02);
INSERT INTO employee_positions_new (EmpNo, Position03, SalCodeS03);
Upvotes: 0
Reputation: 2169
may be something like this:
select EmpNo, Position01 as Position, SalCodeS01 as SalCode from employees_table
union
select EmpNo, Position02 as Position, SalCodeS02 as SalCode from employees_table
union
select EmpNo, Position03 as Position, SalCodeS03 as SalCode from employees_table
order by EmpNo, Position
Upvotes: 1