一个序列是一个永久的数据库对象,你不能像那样动态地定义一个;即使使用序列,您也可以使用 nextval 来获取值。
Oracle 必须知道查询在解析时将产生多少列,因此您无法在运行时确定多少列,而这正是您所尝试的。如果你真的不知道,那么你必须使用动态 SQL;或 XML 数据透视表,然后您必须将其解压缩。 From the documentation:
XML 关键字允许pivot_in_clause 包含子查询或通配符关键字ANY。当pivot_in_clause 值事先未知时,子查询和ANY 通配符很有用。
在这种情况下,使用另一个查询生成语句会更简单 - 无需键入所有值。您可以通过分层查询或递归 CTE 获得数字 1-100,然后可以使用listagg() 将它们组成一个值列表:
with t (n) as (
select 1 from dual
union all
select n + 1 from t where n < 100
)
select listagg(n, ', ') within group (order by n)
from t;
LISTAGG(N,',')WITHINGROUP(ORDERBYN)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100
然后您可以将其用作构成整个查询的字符串的一部分:
with t (n) as (
select 1 from dual
union all
select n + 1 from t where n < 100
)
select q'^select *
from your_table
pivot (
max(case effect when 'incr' then 1 when 'decr' then -1 end)
for col in (^' || listagg(n, ', ') within group (order by n) || q'^)
)
order by usr^'
from t;
Q'^SELECT*FROMYOUR_TABLEPIVOT(MAX(CASEEFFECTWHEN'INCR'THEN1WHEN'DECR'THEN-1END)FORCOLIN(^'||LISTAGG(N,',')WITHINGROUP(ORDERBYN)||Q'^))ORDERBYUSR^'
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
select *
from your_table
pivot (
max(case effect when 'incr' then 1 when 'decr' then -1 end)
for col in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)
)
order by usr
然后运行生成的语句:
select *
from your_table
pivot (
max(case effect when 'incr' then 1 when 'decr' then -1 end)
for col in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)
)
order by usr;
U 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
a 1 -1 -1
b -1 -1 -1
c -1 1 1
当然,您可以将生成的语句作为动态 SQL 运行,但如果可以的话,复制和粘贴会更简单。
您也可以更改此设置以使 CTE 仅提取表中实际存在的值:
t (n) as (
select distinct col from your_table
)
select q'^select *
from your_table
pivot (
max(case effect when 'incr' then 1 when 'decr' then -1 end)
for col in (^' || listagg(n, ', ') within group (order by n) || q'^)
)
order by usr^'
from t;
生成:
select *
from your_table
pivot (
max(case effect when 'incr' then 1 when 'decr' then -1 end)
for col in (1, 5, 20, 40, 100)
)
order by usr
在运行时会给出更易于管理的最终结果:
U 1 5 20 40 100
- ---------- ---------- ---------- ---------- ----------
a 1 -1 -1
b -1 -1 -1
c -1 1 1