如何在不插入值的情况下在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?