创建多个级别的层次结构,其中每个节点都有随机数量的子节点

Sol*_*zky 16 sql-server hierarchy random t-sql

我需要创建一些涉及层次结构的测试数据。我可以让它变得简单并做几个CROSS JOINs,但这会给我一个完全统一/没有任何变化的结构。这不仅看起来很乏味,而且测试数据缺乏变化有时会掩盖原本会发现的问题。所以,我想生成一个遵循以下规则的非统一层次结构:

  • 3 层深
    • 1 级随机 5 - 20 个节点
    • 级别 2 是 1 - 10 个节点,每个级别 1 的每个节点随机
    • 级别 3 是 1 - 5 个节点,每个级别 2 的每个节点随机
  • 所有分支都将有 3 层深。在这一点上,深度的均匀性是可以的。
  • 任何给定级别上的子节点的名称都可以重叠(即子节点的名称在同一级别的所有节点中不需要是唯一的)。
  • 术语“随机”在这里定义为伪随机,而不是唯一随机。这需要提及,因为术语“随机”通常用于表示“不产生重复的给定集合的随机排序”。我接受 random = random 并且如果级别 1 的每个节点的子节点数仅为 4、7 和 8,即使级别 1 上的 20 个节点每个节点的潜在分布为 1 - 10 个子节点,那很好,因为这就是随机。
  • 尽管使用嵌套WHILE循环可以很容易地做到这一点,但首选是找到一种基于集合的方法。一般而言,生成测试数据没有生产代码对效率的要求,但尝试基于集合的方法可能会更具教育意义,并有助于在未来找到基于集合的方法来解决问题。因此WHILE,不排除循环,但只有在不可能使用基于集合的方法时才能使用循环。
  • Set-based = 理想情况下是单个查询,无论 CTE、APPLY 等如何。因此使用现有或内联数字表很好。使用 WHILE / CURSOR / 程序方法是行不通的。我想将部分数据暂存到临时表或表变量中就可以了,只要操作都是基于集合的,没有循环。然而,话虽如此,单查询方法可能比多查询更受青睐,除非可以证明多查询方法实际上更好。另请记住,“更好”的构成通常是主观的;-)。还请记住,前一句中“典型地”的用法也是主观的。
  • 任何版本的 SQL Server(我想是 2005 和更新版本)都可以。
  • 只有纯 T-SQL:没有那些愚蠢的 SQLCLR 东西!!至少在生成数据方面。将使用 SQLCLR 创建目录和文件。但在这里,我只是专注于产生要创造的价值。
  • T-SQL 多语句 TVF 被认为是过程性的,而不是基于集合的,即使在外面它们掩盖了集合中的过程方法。有时这是绝对合适的。这不是其中之一。同样,T-SQL 标量函数也是不允许的,不仅因为它们也是过程性的,而且查询优化器有时会缓存它们的值并重复它,从而导致输出与预期不同。
  • T-SQL 内联 TVF(又名 iTVF)是 okey-dokey,因为它们是基于集合的,并且实际上与 using 相同[ CROSS | OUTER ] APPLY,这在上面说是可以的。
  • 查询的重复执行应该产生与先前运行大不相同的结果。
  • 澄清更新 1:最终结果集应表示为对于 Level3 的每个不同节点都有一行,具有从 Level1 开始的完整路径。这意味着 Level1 和 Level2 值必须在一行或多行中重复,除非只有一个 Level2 节点只包含一个 Level3 节点。
  • 澄清更新 2:对于每个节点都有一个名称或标签,而不仅仅是一个数字,这是一个非常强烈的偏好。这将允许生成的测试数据更有意义和现实。

我不确定这些附加信息是否重要,但以防万一它有助于了解一些上下文,测试数据与我对这个问题的回答有关:

将 XML 文件导入 SQL Server 2012

虽然此时不相关,但生成此层次结构的最终目标是创建一个目录结构来测试递归文件系统方法。级别 1 和 2 将是目录,级别 3 最终将是文件名。我四处搜索(在这里和通过谷歌搜索),只找到了一个生成随机层次结构的参考:

Linux:创建随机目录/文件层次结构

这个问题(在 StackOverflow 上)实际上与预期结果非常接近,因为它也试图创建一个用于测试的目录结构。但是这个问题(和答案)集中在 Linux/Unix shell 脚本上,而不是我们生活的基于集合的世界。

现在,我知道如何生成随机数据,并且我已经在这样做以创建文件的内容,以便它们也可以显示变化。这里的棘手部分是每个集合中的元素数量是随机的,而不是特定的字段。并且,每个节点内的元素数量需要与同一级别上的其他节点随机。

示例层次结构

     Level 1
              Level 3
|---- A
|     |-- 1
|     |   |--- I
|     |
|     |-- 2
|         |--- III
|         |--- VI
|         |--- VII
|         |--- IX
|
|---- B
|     |-- 87
|         |--- AAA
|         |--- DDD
|
|---- C
      |-- ASDF
      |   |--- 11
      |   |--- 22
      |   |--- 33
      |
      |-- QWERTY
      |   |--- beft
      |
      |-- ROYGBP
          |--- Poi
          |--- Moi
          |--- Soy
          |--- Joy
          |--- Roy
Run Code Online (Sandbox Code Playgroud)

描述上述层次结构的示例结果集

Level 1    Level 2    Level 3
A          1          I
A          2          III
A          2          VI
A          2          VII
A          2          IX
B          87         AAA
B          87         DDD
C          ASDF       11
C          ASDF       22
C          ASDF       33
C          QWERTY     beft
C          ROYGBP     Poi
C          ROYGBP     Moi
C          ROYGBP     Soy
C          ROYGBP     Joy
C          ROYGBP     Roy
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 9

OP 的注意:首选解决方案是第 4 个/最后一个代码块)

在我看来,XML 是这里使用的数据结构的明显选择。

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)

select top(5 + abs(checksum(newid())) % 15)
  N1.N as '@Value',
  (
  select top(1 + abs(checksum(newid())) % 10)
    N2.N as '@Value',
    (
    select top(1 + abs(checksum(newid())) % 5)
      N3.N as '@Value'
    from N as N3
    where N2.N > 0
    for xml path('Level3'), type
    )
  from N as N2
  where N1.N > 0
  for xml path('Level2'), type
  )
from N as N1
for xml path('Level1'), root('Root');
Run Code Online (Sandbox Code Playgroud)

使 SQL Servertop()为每个节点使用不同值的技巧是使子查询相关联。N1.N > 0N2.N > 0

扁平化 XML:

declare @X xml;

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)
select @X  = (
             select top(5 + abs(checksum(newid())) % 15)
               N1.N as '@Value',
               (
               select top(1 + abs(checksum(newid())) % 10)
                 N2.N as '@Value',
                 (
                 select top(1 + abs(checksum(newid())) % 5)
                   N3.N as '@Value'
                 from N as N3
                 where N2.N > 0
                 for xml path('Level3'), type
                 )
               from N as N2
               where N1.N > 0
               for xml path('Level2'), type
               )
             from N as N1
             for xml path('Level1')
             );


select L1.X.value('@Value', 'varchar(10)')+'\'+
       L2.X.value('@Value', 'varchar(10)')+'\'+
       L3.X.value('@Value', 'varchar(10)')
from @X.nodes('/Level1') as L1(X)
  cross apply L1.X.nodes('Level2') as L2(X)
  cross apply L2.X.nodes('Level3') as L3(X);
Run Code Online (Sandbox Code Playgroud)

还有一个完全没有 XML 的版本。

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)
select cast(N1.N as varchar(10))+'\'+
       cast(N2.N as varchar(10))+'\'+
       cast(N3.N as varchar(10))
from (
     select top(5 + abs(checksum(newid())) % 15)
       N.N
     from N
     ) as N1
  cross apply
     (
     select top(1 + abs(checksum(newid())) % 10)
       N.N
     from N
     where N1.N > 0
     ) as N2
  cross apply
     (
     select top(1 + abs(checksum(newid())) % 5)
       N.N
     from N
     where N2.N > 0
     ) as N3;
Run Code Online (Sandbox Code Playgroud)

关联N1.N > 0N2.N > 0仍然是重要的。

使用带有 20 个名称的表的版本,而不仅仅是整数。

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)

select top(5 + abs(checksum(newid())) % 15)
  N1.N as '@Value',
  (
  select top(1 + abs(checksum(newid())) % 10)
    N2.N as '@Value',
    (
    select top(1 + abs(checksum(newid())) % 5)
      N3.N as '@Value'
    from N as N3
    where N2.N > 0
    for xml path('Level3'), type
    )
  from N as N2
  where N1.N > 0
  for xml path('Level2'), type
  )
from N as N1
for xml path('Level1'), root('Root');
Run Code Online (Sandbox Code Playgroud)


Vla*_*nov 7

那很有趣。

我的目标是在正确链接的层次结构中生成给定数量的级别,每个级别具有随机数量的子行。一旦这个结构准备好,就可以很容易地向其中添加额外的信息,如文件和文件夹名称。

所以,我想生成一个用于存储树的经典表:

ID int NOT NULL
ParentID int NULL
Lvl int NOT NULL
Run Code Online (Sandbox Code Playgroud)

由于我们正在处理递归,递归 CTE 似乎是一个自然的选择。

我需要一张数字表。表中的数字应从 1 开始。表中至少应有 20 个数字:MAX(LvlMax)

CREATE TABLE [dbo].[Numbers](
    [Number] [int] NOT NULL,
CONSTRAINT [PK_Numbers] PRIMARY KEY CLUSTERED 
(
    [Number] ASC
));

INSERT INTO Numbers(Number)
SELECT TOP(1000)
    ROW_NUMBER() OVER(ORDER BY S.object_id)  AS Number
FROM
    sys.all_objects AS S
ORDER BY Number;
Run Code Online (Sandbox Code Playgroud)

数据生成参数应存储在表中:

DECLARE @Intervals TABLE (Lvl int, LvlMin int, LvlMax int);
INSERT INTO @Intervals (Lvl, LvlMin, LvlMax) VALUES
(1, 5, 20),
(2, 1, 10),
(3, 1, 5);
Run Code Online (Sandbox Code Playgroud)

请注意,该查询非常灵活,所有参数都集中在一处。如果需要,您可以添加更多级别,只需添加额外的一行参数。

为了使这种动态生成成为可能,我必须记住下一级的随机行数,所以我有一个额外的 column ChildRowCount

生成unique IDs也有些棘手。我对每 1 个父行 100 个子行的限制进行了硬编码,以确保IDs不会重复。这就是它POWER(100, CTE.Lvl)的内容。因此,存在很大的差距IDs。该数字可能是MAX(LvlMax),但为了简单起见,我在查询中放置了常量 100。级别数不是硬编码的,而是由 决定的@Intervals

这个公式

CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5
Run Code Online (Sandbox Code Playgroud)

生成范围内的随机浮点数[0..1),然后将其缩放到所需的间隔。

查询逻辑很简单。它是递归的。第一步生成一组第一级的行。行数由 中的随机数决定TOP。此外,对于每一行,存储在ChildRowCount.

递归部分用于CROSS APPLY为每个父行生成给定数量的子行。我不得不使用WHERE Numbers.Number <= CTE.ChildRowCount代替TOP(CTE.ChildRowCount),因为TOP在 CTE 的递归部分不允许使用。之前不知道 SQL Server 的这个限制。

WHERE CTE.ChildRowCount IS NOT NULL 停止递归。

SQL小提琴

WITH
CTE
AS
(
    SELECT 
        TOP(CAST(
            (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
            (
                1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = 1)
                  - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 1)
            )
            + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 1)
            AS int))
        Numbers.Number AS ID
        ,NULL AS ParentID
        ,1 AS Lvl
        ,CAST(
            (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
            (
                1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = 2)
                  - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 2)
            )
            + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 2)
            AS int) AS ChildRowCount
    FROM Numbers
    ORDER BY Numbers.Number

    UNION ALL

    SELECT
        CA.Number + CTE.ID * POWER(100, CTE.Lvl) AS ID
        ,CTE.ID AS ParentID
        ,CTE.Lvl + 1 AS Lvl
        ,CA.ChildRowCount
    FROM
        CTE
        CROSS APPLY
        (
            SELECT
                Numbers.Number
                ,CAST(
                    (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
                    (
                    1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                      - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                    )
                    + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                    AS int) AS ChildRowCount
            FROM Numbers
            WHERE Numbers.Number <= CTE.ChildRowCount
        ) AS CA
    WHERE
        CTE.ChildRowCount IS NOT NULL
)
SELECT *
FROM CTE
ORDER BY Lvl, ParentID, ID;
Run Code Online (Sandbox Code Playgroud)

结果(如果幸运的话,最多可以有 20 + 20*10 + 200*5 = 1220 行)

+---------+----------+-----+-------------------+
|   ID    | ParentID | Lvl | ChildRowCount     |
+---------+----------+-----+-------------------+
|       1 | NULL     |   1 | 3                 |
|       2 | NULL     |   1 | 1                 |
|       3 | NULL     |   1 | 6                 |
|       4 | NULL     |   1 | 5                 |
|       5 | NULL     |   1 | 3                 |
|       6 | NULL     |   1 | 7                 |
|       7 | NULL     |   1 | 1                 |
|       8 | NULL     |   1 | 6                 |
|     101 | 1        |   2 | 3                 |
|     102 | 1        |   2 | 5                 |
|     103 | 1        |   2 | 1                 |
|     201 | 2        |   2 | 5                 |
|     301 | 3        |   2 | 4                 |
|     302 | 3        |   2 | 5                 |
|     303 | 3        |   2 | 1                 |
|     304 | 3        |   2 | 2                 |
|     305 | 3        |   2 | 4                 |
|     306 | 3        |   2 | 3                 |
|     401 | 4        |   2 | 3                 |
|     402 | 4        |   2 | 1                 |
|     403 | 4        |   2 | 2                 |
|     404 | 4        |   2 | 2                 |
|     405 | 4        |   2 | 4                 |
|     501 | 5        |   2 | 1                 |
|     502 | 5        |   2 | 3                 |
|     503 | 5        |   2 | 5                 |
|     601 | 6        |   2 | 2                 |
|     602 | 6        |   2 | 5                 |
|     603 | 6        |   2 | 3                 |
|     604 | 6        |   2 | 3                 |
|     605 | 6        |   2 | 4                 |
|     606 | 6        |   2 | 5                 |
|     607 | 6        |   2 | 4                 |
|     701 | 7        |   2 | 2                 |
|     801 | 8        |   2 | 2                 |
|     802 | 8        |   2 | 3                 |
|     803 | 8        |   2 | 3                 |
|     804 | 8        |   2 | 3                 |
|     805 | 8        |   2 | 5                 |
|     806 | 8        |   2 | 2                 |
| 1010001 | 101      |   3 | NULL              |
| 1010002 | 101      |   3 | NULL              |
| 1010003 | 101      |   3 | NULL              |
| 1020001 | 102      |   3 | NULL              |
| 1020002 | 102      |   3 | NULL              |
| 1020003 | 102      |   3 | NULL              |
| 1020004 | 102      |   3 | NULL              |
| 1020005 | 102      |   3 | NULL              |
| 1030001 | 103      |   3 | NULL              |
| 2010001 | 201      |   3 | NULL              |
| 2010002 | 201      |   3 | NULL              |
| 2010003 | 201      |   3 | NULL              |
| 2010004 | 201      |   3 | NULL              |
| 2010005 | 201      |   3 | NULL              |
| 3010001 | 301      |   3 | NULL              |
| 3010002 | 301      |   3 | NULL              |
| 3010003 | 301      |   3 | NULL              |
| 3010004 | 301      |   3 | NULL              |
| 3020001 | 302      |   3 | NULL              |
| 3020002 | 302      |   3 | NULL              |
| 3020003 | 302      |   3 | NULL              |
| 3020004 | 302      |   3 | NULL              |
| 3020005 | 302      |   3 | NULL              |
| 3030001 | 303      |   3 | NULL              |
| 3040001 | 304      |   3 | NULL              |
| 3040002 | 304      |   3 | NULL              |
| 3050001 | 305      |   3 | NULL              |
| 3050002 | 305      |   3 | NULL              |
| 3050003 | 305      |   3 | NULL              |
| 3050004 | 305      |   3 | NULL              |
| 3060001 | 306      |   3 | NULL              |
| 3060002 | 306      |   3 | NULL              |
| 3060003 | 306      |   3 | NULL              |
| 4010001 | 401      |   3 | NULL              |
| 4010002 | 401      |   3 | NULL              |
| 4010003 | 401      |   3 | NULL              |
| 4020001 | 402      |   3 | NULL              |
| 4030001 | 403      |   3 | NULL              |
| 4030002 | 403      |   3 | NULL              |
| 4040001 | 404      |   3 | NULL              |
| 4040002 | 404      |   3 | NULL              |
| 4050001 | 405      |   3 | NULL              |
| 4050002 | 405      |   3 | NULL              |
| 4050003 | 405      |   3 | NULL              |
| 4050004 | 405      |   3 | NULL              |
| 5010001 | 501      |   3 | NULL              |
| 5020001 | 502      |   3 | NULL              |
| 5020002 | 502      |   3 | NULL              |
| 5020003 | 502      |   3 | NULL              |
| 5030001 | 503      |   3 | NULL              |
| 5030002 | 503      |   3 | NULL              |
| 5030003 | 503      |   3 | NULL              |
| 5030004 | 503      |   3 | NULL              |
| 5030005 | 503      |   3 | NULL              |
| 6010001 | 601      |   3 | NULL              |
| 6010002 | 601      |   3 | NULL              |
| 6020001 | 602      |   3 | NULL              |
| 6020002 | 602      |   3 | NULL              |
| 6020003 | 602      |   3 | NULL              |
| 6020004 | 602      |   3 | NULL              |
| 6020005 | 602      |   3 | NULL              |
| 6030001 | 603      |   3 | NULL              |
| 6030002 | 603      |   3 | NULL              |
| 6030003 | 603      |   3 | NULL              |
| 6040001 | 604      |   3 | NULL              |
| 6040002 | 604      |   3 | NULL              |
| 6040003 | 604      |   3 | NULL              |
| 6050001 | 605      |   3 | NULL              |
| 6050002 | 605      |   3 | NULL              |
| 6050003 | 605      |   3 | NULL              |
| 6050004 | 605      |   3 | NULL              |
| 6060001 | 606      |   3 | NULL              |
| 6060002 | 606      |   3 | NULL              |
| 6060003 | 606      |   3 | NULL              |
| 6060004 | 606      |   3 | NULL              |
| 6060005 | 606      |   3 | NULL              |
| 6070001 | 607      |   3 | NULL              |
| 6070002 | 607      |   3 | NULL              |
| 6070003 | 607      |   3 | NULL              |
| 6070004 | 607      |   3 | NULL              |
| 7010001 | 701      |   3 | NULL              |
| 7010002 | 701      |   3 | NULL              |
| 8010001 | 801      |   3 | NULL              |
| 8010002 | 801      |   3 | NULL              |
| 8020001 | 802      |   3 | NULL              |
| 8020002 | 802      |   3 | NULL              |
| 8020003 | 802      |   3 | NULL              |
| 8030001 | 803      |   3 | NULL              |
| 8030002 | 803      |   3 | NULL              |
| 8030003 | 803      |   3 | NULL              |
| 8040001 | 804      |   3 | NULL              |
| 8040002 | 804      |   3 | NULL              |
| 8040003 | 804      |   3 | NULL              |
| 8050001 | 805      |   3 | NULL              |
| 8050002 | 805      |   3 | NULL              |
| 8050003 | 805      |   3 | NULL              |
| 8050004 | 805      |   3 | NULL              |
| 8050005 | 805      |   3 | NULL              |
| 8060001 | 806      |   3 | NULL              |
| 8060002 | 806      |   3 | NULL              |
+---------+----------+-----+-------------------+
Run Code Online (Sandbox Code Playgroud)

生成完整路径而不是链接层次结构

如果我们只对N深度的完整路径级别感兴趣,我们可以从 CTE 中省略IDParentID。如果我们在补充表中有可能名称的列表Names,则很容易在 CTE 中从该表中选择它们。Names每个级别的表应该有足够的行:级别 1 为 20,级别 2 为 10,级别 3 为 5;20+10+5 = 总共 35。没有必要为每个级别设置不同的行集,但很容易正确设置,所以我做到了。

DECLARE @Names TABLE (Lvl int, Name nvarchar(4000), SeqNumber int);

-- First level: AAA, BBB, CCC, etc.
INSERT INTO @Names (Lvl, Name, SeqNumber)
SELECT 1, REPLICATE(CHAR(Number+64), 3) AS Name, Number AS SeqNumber
FROM Numbers
WHERE Number <= 20;

-- Second level: 001, 002, 003, etc.
INSERT INTO @Names (Lvl, Name, SeqNumber)
SELECT 2, REPLACE(STR(Number, 3), ' ', '0') AS Name, Number AS SeqNumber
FROM Numbers
WHERE Number <= 10;

-- Third level: I, II, III, IV, V
INSERT INTO @Names (Lvl, Name, SeqNumber) VALUES
(3, 'I',   1),
(3, 'II',  2),
(3, 'III', 3),
(3, 'IV',  4),
(3, 'V',   5);
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle这是最后的查询。我把FullPath分成FilePathFileName

ID int NOT NULL
ParentID int NULL
Lvl int NOT NULL
Run Code Online (Sandbox Code Playgroud)

结果

+-------------+----------+----------+
|  FullPath   | FilePath | FileName |
+-------------+----------+----------+
| AAA\001\I   | AAA\001  | I        |
| AAA\001\II  | AAA\001  | II       |
| AAA\002\I   | AAA\002  | I        |
| AAA\002\II  | AAA\002  | II       |
| AAA\002\III | AAA\002  | III      |
| AAA\002\IV  | AAA\002  | IV       |
| AAA\002\V   | AAA\002  | V        |
| AAA\003\I   | AAA\003  | I        |
| AAA\003\II  | AAA\003  | II       |
| AAA\003\III | AAA\003  | III      |
| AAA\004\I   | AAA\004  | I        |
| AAA\004\II  | AAA\004  | II       |
| AAA\004\III | AAA\004  | III      |
| AAA\004\IV  | AAA\004  | IV       |
| BBB\001\I   | BBB\001  | I        |
| BBB\001\II  | BBB\001  | II       |
| CCC\001\I   | CCC\001  | I        |
| CCC\001\II  | CCC\001  | II       |
| CCC\001\III | CCC\001  | III      |
| CCC\001\IV  | CCC\001  | IV       |
| CCC\001\V   | CCC\001  | V        |
| CCC\002\I   | CCC\002  | I        |
| CCC\003\I   | CCC\003  | I        |
| CCC\003\II  | CCC\003  | II       |
| CCC\004\I   | CCC\004  | I        |
| CCC\004\II  | CCC\004  | II       |
| CCC\005\I   | CCC\005  | I        |
| CCC\005\II  | CCC\005  | II       |
| CCC\005\III | CCC\005  | III      |
| CCC\006\I   | CCC\006  | I        |
| CCC\006\II  | CCC\006  | II       |
| CCC\006\III | CCC\006  | III      |
| CCC\006\IV  | CCC\006  | IV       |
| CCC\007\I   | CCC\007  | I        |
| CCC\007\II  | CCC\007  | II       |
| CCC\007\III | CCC\007  | III      |
| CCC\007\IV  | CCC\007  | IV       |
| CCC\008\I   | CCC\008  | I        |
| CCC\008\II  | CCC\008  | II       |
| CCC\008\III | CCC\008  | III      |
| CCC\009\I   | CCC\009  | I        |
| CCC\009\II  | CCC\009  | II       |
| CCC\009\III | CCC\009  | III      |
| CCC\009\IV  | CCC\009  | IV       |
| CCC\010\I   | CCC\010  | I        |
| CCC\010\II  | CCC\010  | II       |
| CCC\010\III | CCC\010  | III      |
| DDD\001\I   | DDD\001  | I        |
| DDD\001\II  | DDD\001  | II       |
| DDD\001\III | DDD\001  | III      |
| DDD\001\IV  | DDD\001  | IV       |
| DDD\002\I   | DDD\002  | I        |
| DDD\003\I   | DDD\003  | I        |
| DDD\003\II  | DDD\003  | II       |
| DDD\003\III | DDD\003  | III      |
| DDD\003\IV  | DDD\003  | IV       |
| DDD\004\I   | DDD\004  | I        |
| DDD\004\II  | DDD\004  | II       |
| DDD\004\III | DDD\004  | III      |
| DDD\005\I   | DDD\005  | I        |
| DDD\006\I   | DDD\006  | I        |
| DDD\006\II  | DDD\006  | II       |
| DDD\006\III | DDD\006  | III      |
| DDD\007\I   | DDD\007  | I        |
| DDD\007\II  | DDD\007  | II       |
| DDD\008\I   | DDD\008  | I        |
| DDD\008\II  | DDD\008  | II       |
| DDD\008\III | DDD\008  | III      |
| DDD\009\I   | DDD\009  | I        |
| DDD\009\II  | DDD\009  | II       |
| DDD\010\I   | DDD\010  | I        |
| DDD\010\II  | DDD\010  | II       |
| DDD\010\III | DDD\010  | III      |
| DDD\010\IV  | DDD\010  | IV       |
| DDD\010\V   | DDD\010  | V        |
| EEE\001\I   | EEE\001  | I        |
| EEE\001\II  | EEE\001  | II       |
| FFF\001\I   | FFF\001  | I        |
| FFF\002\I   | FFF\002  | I        |
| FFF\002\II  | FFF\002  | II       |
| FFF\003\I   | FFF\003  | I        |
| FFF\003\II  | FFF\003  | II       |
| FFF\003\III | FFF\003  | III      |
| FFF\003\IV  | FFF\003  | IV       |
| FFF\003\V   | FFF\003  | V        |
| FFF\004\I   | FFF\004  | I        |
| FFF\004\II  | FFF\004  | II       |
| FFF\004\III | FFF\004  | III      |
| FFF\004\IV  | FFF\004  | IV       |
| FFF\005\I   | FFF\005  | I        |
| FFF\006\I   | FFF\006  | I        |
| FFF\007\I   | FFF\007  | I        |
| FFF\007\II  | FFF\007  | II       |
| FFF\007\III | FFF\007  | III      |
| GGG\001\I   | GGG\001  | I        |
| GGG\001\II  | GGG\001  | II       |
| GGG\001\III | GGG\001  | III      |
| GGG\002\I   | GGG\002  | I        |
| GGG\003\I   | GGG\003  | I        |
| GGG\003\II  | GGG\003  | II       |
| GGG\003\III | GGG\003  | III      |
| GGG\004\I   | GGG\004  | I        |
| GGG\004\II  | GGG\004  | II       |
| HHH\001\I   | HHH\001  | I        |
| HHH\001\II  | HHH\001  | II       |
| HHH\001\III | HHH\001  | III      |
| HHH\002\I   | HHH\002  | I        |
| HHH\002\II  | HHH\002  | II       |
| HHH\002\III | HHH\002  | III      |
| HHH\002\IV  | HHH\002  | IV       |
| HHH\002\V   | HHH\002  | V        |
| HHH\003\I   | HHH\003  | I        |
| HHH\003\II  | HHH\003  | II       |
| HHH\003\III | HHH\003  | III      |
| HHH\003\IV  | HHH\003  | IV       |
| HHH\003\V   | HHH\003  | V        |
| HHH\004\I   | HHH\004  | I        |
| HHH\004\II  | HHH\004  | II       |
| HHH\004\III | HHH\004  | III      |
| HHH\004\IV  | HHH\004  | IV       |
| HHH\004\V   | HHH\004  | V        |
| HHH\005\I   | HHH\005  | I        |
| HHH\005\II  | HHH\005  | II       |
| HHH\005\III | HHH\005  | III      |
| HHH\005\IV  | HHH\005  | IV       |
| HHH\005\V   | HHH\005  | V        |
| HHH\006\I   | HHH\006  | I        |
| HHH\007\I   | HHH\007  | I        |
| HHH\007\II  | HHH\007  | II       |
| HHH\007\III | HHH\007  | III      |
| HHH\008\I   | HHH\008  | I        |
| HHH\008\II  | HHH\008  | II       |
| HHH\008\III | HHH\008  | III      |
| HHH\008\IV  | HHH\008  | IV       |
| HHH\008\V   | HHH\008  | V        |
+-------------+----------+----------+
Run Code Online (Sandbox Code Playgroud)