不带聚合的SQL pivot
更新 我已经修改了SQL FIDLE,以使部门名称更能反映我想要达到的目标。如果你看小提琴,有3个select语句 从数据中按正确顺序列出部门 这是我尝试旋转的结果 假选择,以便显示我想要达到的目标 在我的透视尝试的结果中,第二行显示departmentLevel1为空,departmentLevel3不应在此行中。我尝试了行数和分区的各种组合,但我似乎无法解决这个问题。完全沮丧 这是我最新的小提琴 在你投票结束之前 请阅读此问题,然后阅读问题的副本。所提出的问题要简单得多。我的问题不仅是关于数据透视,而且是对数据透视结果进行分组,并比数据透视的开始和停止时间做更多的事情。我想我们只是在看标题。如果你不想阅读整个问题,这是可以的,但不要假设它是与其他一些标题类似的问题相同,请 我意识到我必须有一个聚合,所以我尝试使用max,但我真的只是试图以更表格的方式显示这些信息,以便我可以将其加入到另一个数据集 以下是起始数据:不带聚合的SQL pivot,sql,sql-server,pivot,Sql,Sql Server,Pivot,更新 我已经修改了SQL FIDLE,以使部门名称更能反映我想要达到的目标。如果你看小提琴,有3个select语句 从数据中按正确顺序列出部门 这是我尝试旋转的结果 假选择,以便显示我想要达到的目标 在我的透视尝试的结果中,第二行显示departmentLevel1为空,departmentLevel3不应在此行中。我尝试了行数和分区的各种组合,但我似乎无法解决这个问题。完全沮丧 这是我最新的小提琴 在你投票结束之前 请阅读此问题,然后阅读问题的副本。所提出的问题要简单得多。我的问题不仅是关于数
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
有人对我的错误有什么建议吗?旋转在某种程度上就像分组一样。您需要原始源中的一列作为分组依据。在这种情况下,您没有它,而且他不知道“testsub1”以任何方式连接到“neth test dept”。这里我们需要的是为层次结构建立根。我们可以用一个小的递归CTE将t替换为vDepartmentList:
;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
现在我们有一个根,还有另一个问题:我们只有两个根,但你想在结果中有三行。Pivot运算符将基本上分组到根列上,并将“new sub2”、“new Sub3A”和“should L3”视为都属于“test2”,并生成具有这些值各自最大值的单行
应该有区别的方法,但我在你的数据中看不到。看来,你运气不好。我根据你的视图sql创建了下面的sql。你几乎可以在那里得到结果
我使用@temp table删除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
结果
希望这对您有所帮助因为您需要返回层次结构数据结构的3个级别,所以使用联接而不是枢轴可能会更容易。首先返回父行:
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;
看
似乎使用联接而不是枢轴更容易得到结果。这将使用源数据,而不是您创建的递归视图。这产生了以下结果:
| 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;
看。然后,您可以使用WHERE子句进行一些筛选,以返回包含您需要的所有部门值的行 在子查询中使用row_number为parentid级别中的每个项创建唯一的值。这将允许返回多行。可能重复的行不是重复的行。部门级别的复杂性使其与简单地旋转开始和停止时间大不相同。也许这是我的问题的一部分,我试着去做很多事情once@bluefeet感谢您添加了一个行号,现在上面看到的结果至少显示了所有记录,但仍然没有将所有记录都放在正确的行上。我不知道如何正确地对这个结果进行分组。我对这个结果做了sql处理,因为我不容易解释。递归CTE是我试图改变观点的方式,但可能是我做错了。如果你有机会看看小提琴,看看我搞砸了什么,我很感激它。我投你一票,因为你是对的。我将为BlueFoots的简单性做一个标记。真棒@BlueFoots谢谢。我想我把注意力集中在一个复杂的问题上,真的需要退一步,从一个简单的方法来看待它。简单易行@兰斯:是的,当您最初发布它时,它似乎是一个简单的轴心,这就是为什么我建议使用行编号,但一旦您提供了其他详细信息,显然使用联接的查询将更容易
;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;