Sql 生成列表编号
我有一张这样的桌子:Sql 生成列表编号,sql,sql-server,Sql,Sql Server,我有一张这样的桌子: +-------+--------+--------+ | Grp | Party | Member | +-------+--------+--------+ | FC | Party1 | Tom | | FC | Party1 | Alice | | FC | Party2 | John | | FC | Party3 | Mary | | GC | Party2 | Anna | | GC | Party
+-------+--------+--------+
| 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 |
+-------+--------+
我想将表转换为如下列表:
+-------+--------+--------+
| 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 |
+-------+--------+
我尝试了使用行号汇总
,但结果仍然与我想要的相去甚远
;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')
这里有一条路
;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]
家长需要使用densite\u RANK
正确生成层次编号。如果成员
中也有重复项,则将行编号
更改为密集等级
内部CTE
并将distinct添加到最终的选择
查询中
注意:如果您使用的不是SQL SERVER 2012
,请使用+
运算符进行连接,而不是CONCAT
坦白地说,我不会在数据库级别这样做。相反,我将确保输出按{Grp,Party,Member}排序,然后在显示数据时在一次传递中分配“Id”值
但是,如果出于任何原因决定在数据库服务器中执行此操作,则可以使用densite\u 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
此选项不使用densite\u RANK()
,而是使用ROW\u 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;
这将使用densite\u RANK
为ID
获取正确的编号。然后输入数据并标记哪一行是为Grp
、参与方
、或成员
。最后,使用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;
如果订单与成员
无关,则将rnMember
替换为:
rnMember = ROW_NUMBER() OVER(PARTITION BY Grp, Party ORDER BY (SELECT NULL))
2.1.1应该是Anna,对吗?是的,很抱歉输入错误,谢谢。您的结果表中的顺序似乎不太正确。例如,1.1.1不应该是Alice,1.1.2不应该是Tom吗?事实上,顺序是不相关的,所以它可以是任何顺序。不要建议像这样的别名that@Prdp您的意思是什么?不要使用此MyTable.Member,
将别名添加到您的表MyTable MT
,并将其用作参考MT.Member
。在编程中分配id
比循环所有记录花费更多的可读性willdensite\u rank()
比循环所有记录花费更多吗?谢谢,我可以知道will交叉应用
比联合所有
花费更多吗?从客户统计数据来看,union-all
似乎稍好一些。参考的文章表明,CROSS-APPLY
是最好的方法。但是,我的答案与其他答案完全不同,因为我不必使用DISTINCT
3次。尝试测试更多的行。谢谢@Prdp,您的答案很好,但Felix Pamittan的答案排序更合适