我有一张存储员工及其部门的表格。部门表示组织层次结构中的完整路径:
表名: SourceTable
|----------------------------------------------------------------------|
Employee Department
|----------------------------------------------------------------------|
John D. Organization/Department1/Department2
Alexey N. Organization/Department1/Deparment2/Department3
Alan Z. Organization/Department1
Peter P. Organization/Department4
Zara N. Organization/Department4/Department5
|----------------------------------------------------------------------|
我需要规范化这个表并创建两个新表,如下所示:
表:员工
|--------------------------------------------|
Name DepartmentId
|--------------------------------------------|
John D. 3
Alexey N. 4
Alan Z. 2
Peter P. 5
Zara N. 6
| -------------------------------------------- | < / p>
表名:部门
|--------------------------------------------|
Id ParentId Name
|--------------------------------------------|
1 null Organization
2 1 Department1
3 2 Department2
4 3 Department3
5 1 Department4
6 5 Department5
|-------------------------------------------|
我应该使用哪些查询?
提前致谢。
答案 0 :(得分:0)
此处没有单一查询。
让我们先创建设置:
declare @t table (Employee varchar(10), Department varchar(100))
insert @t values
( 'John D.' , 'Organization/Department1/Department2'),
( 'Alexey N.' , 'Organization/Department1/Department2/Department3'),
( 'Alan Z.' , 'Organization/Department1'),
( 'Peter P.' , 'Organization/Department4'),
( 'Zara N.' , 'Organization/Department4/Department5')
declare @d table (Id int identity(1,1), ParentId int, Name varchar(20))
declare @e table (Name varchar(10), DepartmentId int)
我们还需要一个函数来解析字符串reporesenting路径(我们在这里需要数字表,请在SO中搜索如何创建和填充一个的说明):
create function dbo.splitstrings_numbers
(
@list nvarchar(max),
@delimiter nvarchar(5)
)
returns table
with schemabinding
as
return
(
select number, item = substring(@list, number,
charindex(@delimiter, @list + @delimiter, number) - number)
from dbo.numbers
where number <= convert(int, len(@list))
and substring(@delimiter + @list, number, len(@delimiter)) = @delimiter
);
现在我们可以解析路径(进入临时表,我们重用它):
select *, 0 as rn
into #t
from @t
outer apply [dbo].[splitstrings_numbers] (department, '/')
create index IX__t__employee_number on #t (employee, number)
;with x as (
select *, row_number() over (partition by employee order by number desc) rn2
from #t
)
update x set rn = rn2
从现在开始很容易:)
insert @d (name)
select distinct item from #t
;with x as (
select d.parentid, d3.id as new_parentid
from @d d
join (select distinct item, lag(item) over(partition by employee order by rn desc) as parent from #t) d2 on d2.item = d.name
join @d d3 on d2.parent = d3.name
)
update x set parentid = new_parentid
insert @e
select #t.employee, d.id departmentid
from #t
join @d d on #t.item = d.name and #t.rn = 1
select * from @d
select * from @e
答案 1 :(得分:0)
假设部门名称在整个组织中是唯一的。 样本数据
select Employee, Department
into #sample_data
from (
values
('John D. ','Organization/Department1/Department2'),
('Alexey N.','Organization/Department1/Department2/Department3'),
('Alan Z. ','Organization/Department1'),
('Peter P. ','Organization/Department4'),
('Zara N. ','Organization/Department4/Department5')
) t(Employee, Department);
使用Jeff Moden的DelimitedSplit8K
(或您选择的任何其他拆分器)拆分路径。它生成编号的项目列表。
select Department as path, d.*
into #tmp
from #sample_data
cross apply dbo.DelimitedSplit8K(Department,'/') d;
部门
select Department = item,
id = row_number() over (order by item),
parent_id=null
into #deps
from (
select distinct item
from #tmp) t;
拥有dept id的员工
select Employee,
id = row_number() over (order by Employee),
dep_id = d.id
into #emps
from #sample_data sd
join #deps d on sd.department like '%'+d.Department;
现在是adjency
update d
set parent_id = d2.id
from #deps d
join (
select distinct child=t1.Item, parent=t2.item
from #tmp t1
join #tmp t2 on t1.path = t2.path and t1.ItemNumber-1 = t2.ItemNumber
) adj
on d.Department = adj.child
join #deps d2 on adj.parent = d2.Department;
检查
select * from #deps;
select * from #emps;
编辑
如果部门不是唯一的,请保持其路径,直到建立联系。这里DelimitedSplit8KWithPath
0是前面的DelimitedSplit8K
返回父路径,只添加了一行,所以最终的SELECT是
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1),
Parent = LEFT(@pString, CASE WHEN l.N1>1 THEN l.N1-2 ELSE 0 END)
FROM cteLen l
工作流程基本相同,查询更短
- 所有部门,包括目前没有员工的部门 select distinct Department = CASE WHEN len(parent)&gt; 0那么父母+'/'ELSE''结束+项目 ,d.parent ,项目 进入#tmp 来自#sample_data 交叉应用dbo.DelimitedSplit8KWithPath(Department,'/')d;
- 部门
选择部门, id = row_number()over(按部门排序), PARENT_ID = NULL 进入#deps 来自#tmp
- 具有部门ID的员工
选择员工, id = row_number()over(按Employee排序), dep_id = d.id 进入#emps 来自#sample_data sd 在sd.department = d.Department加入#deps d;
- 现在是adjency
更新d 设置parent_id = d2.id ,department = item 来自#deps d 在d.Department = adj.Department上加入#tmp adj 在adj.parent = d2.Department;
上加入#deps d2从#deps中选择*; 从#emps;
中选择*