如何在不插入值的情况下在 sql 中创建动态行?

How to create dynamic row in sql without inserting a value?

我需要根据 SQL 查询获取的结果添加动态行。我编写了一个显示如下结果的查询:

Value Name
1 Test 1
2 Test 2
. .
n n

上面的 SQL 结果将 return 一个动态的行数。 (行数不固定)

所以我想添加一个列,其中包含基于行数的 Parent1、Parent2 等值。假设我的查询 return 总共有 300 行,那么第一行应该在列 Value 和 In name 中命名为 Parent1,然后我的查询结果直到第 150 行,然后是另一个动态行,其值列为 Parent2 字段和像下面这样 table.

Value Name
Parent1 Parent 1
1 Test 1
2 Test 2
. .
Parent2 Parent2
151 Test 151
. .
n n

请注意:我无法使用 DDL 或 DML 命令来实现此目的。

下面的查询将使用 CONNECT BY 生成 parents/non-parents 的列表。您可以将 300 更改为您要生成的行数,并更改查询中的 150 以使父级生成那么多行数。

    SELECT LEVEL,
           CASE
               WHEN MOD (LEVEL, 150) = 0 OR LEVEL = 1
               THEN
                   'Parent' || TO_CHAR (TRUNC (LEVEL / 150) + 1)
               ELSE
                   TO_CHAR (LEVEL)
           END    AS VALUE,
           CASE
               WHEN MOD (LEVEL, 150) = 0 OR LEVEL = 1
               THEN
                   'Parent' || TO_CHAR (TRUNC (LEVEL / 150) + 1)
               ELSE
                   'Test ' || TO_CHAR (LEVEL)
           END    AS VALUE
      FROM DUAL
CONNECT BY LEVEL <= 300;

假设这是您的原始查询

select 
  to_char(rownum) value, 'Test '||rownum name 
from dual 
connect by level <= 6
;
    VALUE NAME                                         
---------- ----------
         1 Test 1                                       
         2 Test 2                                       
         3 Test 3                                       
         4 Test 4                                       
         5 Test 5
         6 Test 6 

并且您想介绍 两行 header Parent 行。

您可以使用 NTILE 将原始查询拆分为按某些列排序的两部分(此处 VALUE

 NTILE(2) OVER (ORDER BY VALUE) nt

更改 NTILE 中的数字以增加拆分。

下面的查询使用原始查询作为基础,计算拆分的NTILE,添加UNION ALL Parent 行。

最重要的是使用 NTILE 数字 (nt) 涵盖 正确顺序 ,来源(第一个 parent 行比数据)和 value.

with dt as ( /* your original query */
select 
  to_char(rownum) value, 'Test '||rownum name 
from dual 
connect by level <= 6
)
select VALUE, NAME,
NTILE(2) OVER (ORDER BY VALUE) nt, /* modify to change split */
1 src
from dt
union all
select 
 'Parent'||rownum value,
 'Parent'||rownum name,
 rownum nt, 0 src
from dual connect by level <= 2 /* modify to change split */
order by nt, src, value; 

VALUE                                          NAME                                                   NT        SRC
---------------------------------------------- ---------------------------------------------- ---------- ----------
Parent1                                        Parent1                                                 1          0
1                                              Test 1                                                  1          1
2                                              Test 2                                                  1          1
3                                              Test 3                                                  1          1
Parent2                                        Parent2                                                 2          0
4                                              Test 4                                                  2          1
5                                              Test 5                                                  2          1
6                                              Test 6                                                  2          1

类似的方法,更动态。

col value for 9999
col name  for a20
define limit = &1
define split = &2
select level as lvl,
        case
               when mod (level, &&split) = 0 or level = 1
               then
                   'parent' || to_char (trunc (level / &&split) + 1)
               else
                   to_char (level)
           end    as name,
         case
               when mod (level, &&split) = 0 or level = 1
               then
                   'parent' || to_char (trunc (level / &&split) + 1)
               else
                   'test ' || to_char (level)
           end as value
from dual
connect by level <= &&limit
/

作为脚本执行,你通知两个参数,值的总数和拆分值。

SQL> @generate.sql 100 50
old   3:                when mod (level, &&split) = 0 or level = 1
new   3:                when mod (level, 50) = 0 or level = 1
old   5:                    'parent' || to_char (trunc (level / &&split) + 1)
new   5:                    'parent' || to_char (trunc (level / 50) + 1)
old  10:                when mod (level, &&split) = 0 or level = 1
new  10:                when mod (level, 50) = 0 or level = 1
old  12:                    'parent' || to_char (trunc (level / &&split) + 1)
new  12:                    'parent' || to_char (trunc (level / 50) + 1)
old  17: connect by level <= &&limit
new  17: connect by level <= 100

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
         1 parent1              parent1
         2 2                    test 2
         3 3                    test 3
         4 4                    test 4
         5 5                    test 5
         6 6                    test 6
         7 7                    test 7
         8 8                    test 8
         9 9                    test 9
        10 10                   test 10
        11 11                   test 11

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        12 12                   test 12
        13 13                   test 13
        14 14                   test 14
        15 15                   test 15
        16 16                   test 16
        17 17                   test 17
        18 18                   test 18
        19 19                   test 19
        20 20                   test 20
        21 21                   test 21
        22 22                   test 22

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        23 23                   test 23
        24 24                   test 24
        25 25                   test 25
        26 26                   test 26
        27 27                   test 27
        28 28                   test 28
        29 29                   test 29
        30 30                   test 30
        31 31                   test 31
        32 32                   test 32
        33 33                   test 33

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        34 34                   test 34
        35 35                   test 35
        36 36                   test 36
        37 37                   test 37
        38 38                   test 38
        39 39                   test 39
        40 40                   test 40
        41 41                   test 41
        42 42                   test 42
        43 43                   test 43
        44 44                   test 44

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        45 45                   test 45
        46 46                   test 46
        47 47                   test 47
        48 48                   test 48
        49 49                   test 49
        50 parent2              parent2
        51 51                   test 51
        52 52                   test 52
        53 53                   test 53
        54 54                   test 54
        55 55                   test 55

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        56 56                   test 56
        57 57                   test 57
        58 58                   test 58
        59 59                   test 59
        60 60                   test 60
        61 61                   test 61
        62 62                   test 62
        63 63                   test 63
        64 64                   test 64
        65 65                   test 65
        66 66                   test 66

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        67 67                   test 67
        68 68                   test 68
        69 69                   test 69
        70 70                   test 70
        71 71                   test 71
        72 72                   test 72
        73 73                   test 73
        74 74                   test 74
        75 75                   test 75
        76 76                   test 76
        77 77                   test 77

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        78 78                   test 78
        79 79                   test 79
        80 80                   test 80
        81 81                   test 81
        82 82                   test 82
        83 83                   test 83
        84 84                   test 84
        85 85                   test 85
        86 86                   test 86
        87 87                   test 87
        88 88                   test 88

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
        89 89                   test 89
        90 90                   test 90
        91 91                   test 91
        92 92                   test 92
        93 93                   test 93
        94 94                   test 94
        95 95                   test 95
        96 96                   test 96
        97 97                   test 97
        98 98                   test 98
        99 99                   test 99

       LVL NAME                 VALUE
---------- -------------------- ----------------------------------------------
       100 parent3              parent3

100 rows selected.