【问题标题】:How to create dynamic row in sql without inserting a value?如何在不插入值的情况下在sql中创建动态行?
【发布时间】: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 个值之后增加父值。基本上,我想根据表中可用的数据添加表中不可用的值,而不将其插入表中。
  • 但是每个父母的规则是一半??

标签: sql oracle oracle-sqldeveloper


【解决方案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.
    

    【讨论】:

      猜你喜欢
      • 2010-11-06
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      • 2011-07-09
      相关资源
      最近更新 更多