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
比循环所有记录花费更多的可读性will
densite\u rank()
比循环所有记录花费更多吗?谢谢,我可以知道will
交叉应用
联合所有
花费更多吗?从客户统计数据来看,
union-all
似乎稍好一些。参考的文章表明,
CROSS-APPLY
是最好的方法。但是,我的答案与其他答案完全不同,因为我不必使用
DISTINCT
3次。尝试测试更多的行。谢谢@Prdp,您的答案很好,但Felix Pamittan的答案排序更合适