更新
我修改了SQL Fiddle,使部门名称更能反映我想要达到的目标。如果你看小提琴,有3个选择语句。
在我的数据透视尝试的结果中,第二行显示为departmentLevel1的null,而departmentLevel3不应该在此行中。我尝试了row_number和分区的各种组合,但我似乎无法弄清楚这一点。 非常沮丧!
这是我最新的小提琴http://sqlfiddle.com/#!3/175af/40
在您决定关闭之前 请阅读此问题,然后阅读重复的问题。选址的问题更为简单。我的问题不仅仅是询问旋转,而是对枢轴结果进行分组,并进行更多的旋转启动和停止时间。我认为只看标题。如果您不想阅读整个问题,但不要认为它与其他具有类似标题的问题相同。
我意识到我必须有一个聚合,所以我尝试使用max,但我真的只是想以更表格的方式显示这些信息,所以我可以将它加入另一个数据集。
以下是起始数据:
select departmentID, departmentParentID, departmentName, departmentGroupSortBy, departmentLevel, sortBy
from vDepartmentList
where regionID = 3
order by departmentGroupSortBy, departmentLevel, sortBy
departmentID departmentParentID departmentName departmentGroupSortBy departmentLevel sortBy
---------------------------------------------------------------------------------------------------
111 neth test dept 1 1 1
115 111 test sub1 1 2 1
112 test2 2 1 2
113 112 new sub2 2 2 1
114 112 new sub 3a 2 2 2
116 114 should L3 2 3 1
如果我运行此查询:
select departmentParentID, [1] as departmentLevel1, [2] as departmentLevel2, [3] as departmentLevel3
from (
select departmentParentID, departmentLevel, departmentName
from vDepartmentList
where regionID = 3
) p
pivot (
max(departmentName)
for departmentLevel in ([1],[2],[3])
) as pvt
order by departmentParentID
我得到了这个结果:
departmentParentID departmentLevel1 departmentLevel2 departmentLevel3
----------------------------------------------------------------------------
test2
111 test sub1
112 new sub2
114 should L3
但我想要得到的是:
departmentParentID departmentLevel1 departmentLevel2 departmentLevel3
----------------------------------------------------------------------------
111 neth test dept test sub1
112 test2 new sub2
112 test2 new sub 3a should L3
有没有人建议我哪里出错了?
答案 0 :(得分:3)
由于您需要返回层次结构数据结构的3个级别,因此使用JOIN而不是使用PIVOT可能要容易得多。您将从返回父行开始:
select p.departmentName
from dbo.department p
where p.departmentParentID is null;
这将为您提供所有顶级行。然后,您开始为所需的每个附加级别添加联接,在您需要总共三个级别的情况下,您将添加两个联接。最终查询如下:
select p.departmentName department1,
c.departmentName department2,
gc.departmentName department3
from dbo.department p -- parent level
left join dbo.department c -- child level
on p.departmentID = c.departmentParentID
left join dbo.department gc -- grandchild level
on c.departmentID = gc.departmentParentID
where p.departmentParentID is null;
似乎使用JOIN而不是使用PIVOT更容易获得结果。这使用源数据而不是您创建的递归视图。这给出了以下结果:
| DEPARTMENT1 | DEPARTMENT2 | DEPARTMENT3 |
|-------------|-------------|--------------|
| depart1 | d1 sub1 | (null) |
| depart2 | d2 sub | (null) |
| depart2 | d2 sub2 | d2s2 subSub1 |
如果您想使用递归查询来获取结果,那么您可以稍微更改当前视图以返回3列名称而不是级别数字:
;with cte as
(
select departmentID,
departmentParentID,
departmentName as Department1,
cast(null as varchar(100)) Department2,
cast(null as varchar(100)) Department3,
1 as Level
from dbo.department
where departmentParentID is null
union all
select d.departmentID,
d.departmentParentID,
Department1,
case when Level + 1 = 2 then d.departmentName else Department2 end,
case when Level + 1 = 3 then d.departmentName else Department3 end,
Level + 1
from dbo.department d
inner join cte h
on d.departmentParentID = h.departmentID
)
select *
from cte;
见SQL Fiddle with Demo。然后,您可以使用WHERE子句进行一些过滤,以返回具有您需要的所有部门值的行。
答案 1 :(得分:1)
我根据你的视图sql创建了下面的sql。你几乎得到了结果。
我使用@temp表来删除order by子句。可能你可以删除实现中的@temp表。
请尝试以下sql:
declare @temp table
(
id int identity,
departmentLevel1 int,
departmentLevel2 int,
departmentLevel3 int,
xRow int
)
insert into @temp
select
d.lvl1, d.lvl2, d.lvl3
,Rrow
from
(
select
a.lvl1, a.lvl2, a.lvl3
,row_number() over(partition by a.lvl1,a.lvl2 order by a.lvl1,a.lvl2) as Rrow
,departmentGroupSortby, departmentlevel, sortby
from
vDepartmentList a
) d
where (d.lvl2 is not null)
order by departmentGroupSortby, departmentlevel, sortby
;
select
c.departmentLevel1 as departmentParentID
,Case
when c.departmentLevel1 = d.departmentid then d.DepartmentName
else
null
end as DepartmentLevel1
,Case
when c.departmentLevel2 = e.departmentid then e.DepartmentName
else
null
end as DepartmentLevel2
,Case
when c.departmentLevel3 = f.departmentid then f.DepartmentName
else
null
end as DepartmentLevel3
--,d.departmentId ,e.departmentid ,f.departmentid
from
(
select
a.id, a.departmentLevel1,a.departmentLevel2,a.departmentLevel3
,a.xRow
from @temp a
inner join
(
select
cast(departmentLevel1 as nvarchar(5)) + cast(departmentLevel2 as nvarchar(5)) as xrow, count(cast(departmentLevel1 as nvarchar(5)) + cast(departmentLevel2 as nvarchar(5))) as xcount
from @temp
group by cast(departmentLevel1 as nvarchar(5)) + cast(departmentLevel2 as nvarchar(5))
) b on cast(a.departmentLevel1 as nvarchar(5)) + cast(a.departmentLevel2 as nvarchar(5)) = b.xrow and a.xRow = b.xcount
) c
left join department d on c.departmentLevel1 = d.departmentId
left join department e on c.departmentLevel2 = e.departmentid
left join department f on c.departmentLevel3 = f.departmentid
的结果强>
departmentParentID DepartmentLevel1 DepartmentLevel2 DepartmentLevel3
------------------ ---------------- ---------------- ----------------
111 depart1 d1 sub1 NULL
112 depart2 d2 sub NULL
112 depart2 d2 sub2 d2s2 subSub1
希望这是帮助
答案 2 :(得分:0)
透视就像分组一样。您需要原始源中的列进行分组。在这种情况下,你没有它,并且他不知道'测试sub1'以任何方式与“测试部门”相关联。我们这里需要的是建立层次结构的根。我们可以使用一个小的递归CTE(用vDepartmentList替换#t):
;with x as (
select *, departmentID as root
from #t
where departmentParentID is null
union all
select #t.*, x.root
from #t
inner join x on #t.departmentParentID = x.departmentID
)
select *
from x
所以现在我们也有一个根也有另一个问题:我们只有两个根,但你想在结果中有三行。枢轴操作员将基本上分组根列,并将处理新的sub2'新的sub 3a'和'应该L3'因为所有人都属于' test2',并生成一行,其中包含这些值的最大值。
应该有一种区分方法,但我无法在您的数据中看到它。所以,看起来,你运气不好。