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

Posted

技术标签:

【中文标题】如何在不插入值的情况下在sql中创建动态行?【英文标题】:How to create dynamic row in sql without inserting a value? 【发布时间】:2021-09-23 13:13:43 【问题描述】:

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

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

上面的 SQL 结果会返回一个动态的行数。 (行数不固定)

所以我想根据行数添加一个列,其中包含 Parent1、Parent2 等值。假设我的查询总共返回 300 行,那么第一行应该在列 Value 和 In name 中命名为 Parent1,然后我的查询结果直到第 150 行,然后是另一个动态行,其中 value 列作为 Parent2 字段,依此类推,如下所示表。

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

请注意:我不能使用 DDL 或 DML 命令来实现这一点。

【问题讨论】:

你说的查询在哪里? 简单查询选择值,name from t1; 因此值存储在 t1 上,对吗??该表中父项和子项之间的关系是什么?如果不是 300 而是 600 或 843 会发生什么? 是的,值存储在 t1 表中,目前该表中没有像父级这样的值。我必须根据表中可用的当前数据显示。如果有 600 或 843 行,则应在每 150 个值之后增加父值。基本上,我想根据表中可用的数据添加表中不可用的值,而不将其插入表中。 但是每个父母的规则是一半?? 【参考方案1】:

假设这是您的原始查询

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 

你想引入两个标题Parent行。

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

 NTILE(2) OVER (ORDER BY VALUE) nt

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

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

最重要的是使用NTILE 数字 (nt)、源(比数据的第一个父行)和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

【讨论】:

使用ntile 的好方法。真的很酷;)【参考方案2】:

下面的查询将使用CONNECT BY 生成父母/非父母的列表。您可以将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;

【讨论】:

【参考方案3】:

类似的方法,更具动态性。

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.

【讨论】:

以上是关于如何在不插入值的情况下在sql中创建动态行?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在不使用(MFC)动态对象创建的情况下在 CSplitterWnd 中创建视图?

如何在不使用渐变维度的情况下在维度中创建数据历史记录?

如何在不进行分组的情况下在Oracle中向SQL结果添加虚拟行

如何在不引用外部 CSS 文件的情况下在 WordPress PHP 文件中创建内联 CSS?

如何在不引用 React 中的动态值的情况下在 URL 中传递“:”?

如何在此扩展程序中创建一个按钮,在不使用操作按钮的情况下在主应用程序中打开特定视图?