我的桌子看起来像这样:
+-------+--------+--------+
| Grp | Party | Member |
+-------+--------+--------+
| FC | Party1 | Tom |
| FC | Party1 | Alice |
| FC | Party2 | John |
| FC | Party3 | Mary |
| GC | Party2 | Anna |
| GC | Party4 | Alex |
| GC | Party5 | Diana |
+-------+--------+--------+
我想将表格转换为如下列表:
+-------+--------+
| ID | Text |
+-------+--------+
| 1 | FC |
| 1.1 | Party1 |
| 1.1.1 | Tom |
| 1.1.2 | Alice |
| 1.2 | Party2 |
| 1.2.1 | John |
| 1.3 | Party3 |
| 1.3.1 | Mary |
| 2 | GC |
| 2.1 | Party2 |
| 2.1.1 | Anna |
| 2.2 | Party4 |
| 2.2.1 | Alex |
| 2.3 | Party5 |
| 2.3.1 | Diana |
+-------+--------+
我已尝试rollup
与row_number
,但结果仍然远离我想要的
;with ctx as (
select * from @test
group by rollup(Grp, Party, Member)
)
select row_number() over (partition by grp order by grp, party, member) as g,
row_number() over (partition by grp, party order by grp, party, member) as p,
row_number() over (partition by grp, party, member order by grp, party, member) as m,
grp, party, member
from ctx
where grp is not null
order by grp, party, member
提前致谢。
修改
这是生成表的SQL,希望这可以帮助
declare @test table (Grp varchar(10), Party varchar(10), Member varchar(20))
insert into @test values ('FC', 'Party1', 'Tom')
insert into @test values ('FC', 'Party1', 'Alice')
insert into @test values ('FC', 'Party2', 'John')
insert into @test values ('FC', 'Party3', 'Mary')
insert into @test values ('GC', 'Party2', 'Anna')
insert into @test values ('GC', 'Party4', 'Alex')
insert into @test values ('GC', 'Party5', 'Diana')
答案 0 :(得分:2)
这是一种方式
;WITH cte
AS (SELECT Dense_rank()OVER (ORDER BY grp) AS g,
Dense_rank()OVER (partition BY grp ORDER BY party) AS p,
Row_number()OVER (partition BY grp, party ORDER BY member) AS m,
grp,
party,
member
FROM @test
WHERE grp IS NOT NULL)
SELECT DISTINCT grp,
Cast(g AS VARCHAR(10)) AS [Text]
FROM cte
UNION ALL
SELECT DISTINCT party,
Concat(g, '.', p)
FROM cte
UNION ALL
SELECT member,
Concat(g, '.', p, '.', m)
FROM cte
ORDER BY [Text]
您需要使用DENSE_RANK
让父母正确生成层次结构编号。如果您在Member
中也有重复内容,请将ROW_NUMBER
更改为DENSE_RANK
内的CTE
,并在最终的select
查询中添加不同内容
注意:如果您使用的内容少于SQL SERVER 2012
,请使用+
运算符进行连接,而不是CONCAT
答案 1 :(得分:2)
这使用DENSE_RANK
为ID
获取正确的编号。然后CROSS APPLY
to unpivot数据并标记哪一行适用于Grp
,Party
或Member
。最后使用WHERE
仅过滤您需要的行:
WITH CteUnpivot AS(
SELECT *
FROM (
SELECT *,
rnGrp = DENSE_RANK() OVER(ORDER BY Grp),
rnParty = DENSE_RANK() OVER(PARTITION BY Grp ORDER BY Party),
rnMember = ROW_NUMBER() OVER(PARTITION BY Grp, Party ORDER BY Member)
FROM test
) t
CROSS APPLY(VALUES
('Grp', Grp),
('Party', Party),
('Member', Member)
) x (col, [Text])
)
SELECT
ID = CASE
WHEN col = 'Grp' THEN CAST(rnGrp AS VARCHAR(3))
WHEN col = 'Party' THEN CAST(rnGrp AS VARCHAR(3)) + '.' + CAST(rnParty AS VARCHAR(3))
WHEN col = 'Member' THEN CAST(rnGrp AS VARCHAR(3)) + '.' + CAST(rnParty AS VARCHAR(3)) + '.' + CAST(rnMember AS VARCHAR(3))
END,
[Text]
FROM CteUnpivot
WHERE
(col = 'Grp' AND rnParty = 1 AND rnMember = 1)
OR (col = 'Party' AND rnMember = 1)
OR (col = 'Member')
ORDER BY rnGrp, rnParty, rnMember;
如果订单与Member
无关,请将rnMember
替换为:
rnMember = ROW_NUMBER() OVER(PARTITION BY Grp, Party ORDER BY (SELECT NULL))
答案 2 :(得分:1)
坦率地说,我不会在数据库级别这样做。相反,我会确保输出按{Grp,Party,Member}排序,然后分配" Id"显示数据时,单次传递的值。
但是,如果您出于某种原因决定在数据库服务器中执行此操作,则可以使用dense_rank()
函数获取每个ID:
;with cte as (
select dense_rank() over (order by Grp) id0,
dense_rank() over (partition by Grp order by Party) id1,
dense_rank() over (partition by Grp, Party order by Member) id2,
Grp, Party, Member
from Table1
), grps as (select distinct id0, Grp from cte),
parties as (select distinct id0, id1, Party from cte),
members as (select distinct id0, id1, id2, Member from cte),
[list] as (
select cast(id0 as varchar(50)) as id, Grp as [Text] from grps
union all
select cast(id0 as varchar(50)) + '.' + cast(id1 as varchar(50)), Party from parties
union all
select cast(id0 as varchar(50)) + '.' + cast(id1 as varchar(50)) + '.' + cast(id2 as varchar(50)), Member from members
)
select id, [Text]
from [list]
order by id
答案 3 :(得分:1)
此选项不使用DENSE_RANK()
但ROW_NUMBER()
,但与发布的其他答案基本相似。
With grps As (
Select Grp, GrpNo = Row_Number() Over (Order By Grp)
From (Select Distinct Grp From MyTable) As MyTable),
parties As (
Select MyTable.Grp, MyTable.Party, grps.GrpNo, PrtyNo = Row_Number() Over (Partition By MyTable.Grp Order By MyTable.Party)
From (Select Distinct Grp, Party From MyTable) As MyTable
Join grps On MyTable.Grp = grps.Grp),
members As (
Select MyTable.Grp, MyTable.Party, MyTable.Member,
parties.GrpNo, parties.PrtyNo, MbrNo = Row_Number() Over (Partition By MyTable.Grp, MyTable.Party Order By #groups.Member)
From MyTable
Join parties On MyTable.Grp = parties.Grp And MyTable.Party = parties.Party)
Select ID = Convert(char(5), GrpNo),
[Text] = Grp
From grps
Union All
Select ID = Convert(char(1), GrpNo) + '.' + Convert(char(1), PrtyNo),
[Text] = Party
From parties
Union All
Select ID = Convert(char(1), GrpNo) + '.' + Convert(char(1), PrtyNo) + '.' + Convert(char(1), MbrNo),
[Text] = Member
From members;