sql 在 IN 语句中定义变量的主函数
sql pivot function with a defined variable in the IN statement
谁能告诉我如何才能完成这项工作?我得到 "ORA-56901: non-constant expression is not allowed for pivot|unpivot values" 或 "ORA-00917: missing comma" 取决于我是否在 IN 语句中将 &mb1 放在引号中。谢谢!
define mb1= ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1);
select *
from
( select COLLECTOR
,Month
,low_activity_days
from dwh_prod.low_activity_days_collect_t) src
pivot
(
sum(low_activity_days)
for month in ('&mb1')
) piv;
您可以改为将替换设置为固定值,这样它就不会尝试在数据透视子句中进行计算。当您处理日期时,您可以生成日期文字:
set termout off
column x_mb1 new_value mb1
select 'date ''' || TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1),
'YYYY-MM-DD') || '''' as x_mb1
from dual;
set termout on
select * from (
select COLLECTOR ,Month ,low_activity_days
from dwh_prod.low_activity_days_collect_t
) src
pivot ( sum(low_activity_days) for month in (&mb1) ) piv;
第一个查询 - 输出被 termout
隐藏生成一个字符串:
select 'date ''' || TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1),
'YYYY-MM-DD') || '''' as x_mb1
from dual;
X_MB1
-----------------
date '2017-03-01'
column ... new_value
command 然后将 &mb
设置为那个。然后,您真正查询中的替换变为:
select * from (
select COLLECTOR ,Month ,low_activity_days
from dwh_prod.low_activity_days_collect_t
) src
pivot ( sum(low_activity_days) for month in (date '2017-03-01') ) piv
您的原始代码的问题在于,您最终在替代主元句中引用了 sysdate
,这会引发 ORA-56901 异常(因为 sysdate
不是不变)。您可以在主元中使用任何固定值,因此您可以做:
define mb1=''01-APR-17''
... for month in (&mb1) ) piv;
将字符串周围的引号作为定义的一部分,或者
define mb1='01-APR-17'
... for month in ('&mb1') ) piv;
没有,或其他变化。但是因为这些最终都是字符串,所以你依赖于隐式日期转换,并且依赖于你的 NLS 设置;使用我生成的日期文字不是问题。如果你真的想使用那种日期格式,你仍然可以这样做:
define mb1='01-APR-17'
... for month in (to_date('&mb1', 'DD-MON-RR')) ) piv;
或 select 使用 new_values
方法的特定格式的日期:
column x_mb1 new_value mb1
select to_char(add_months(trunc(sysdate, 'MM'), -1), 'DD-MON-RR') as x_mb1 from dual;
... for month in (to_date('&mb1', 'DD-MON-RR')) ) piv;
不过,使用日期文字格式对我来说仍然更简单。
我不确定为什么旋转单个值特别有用。也许你真正的查询做的更多,但简单的聚合和过滤器在这里看起来更合适:
select collector, sum(low_activity_days)
from low_activity_days_collect_t
where month = add_months(trunc(sysdate, 'MM'), -1)
group by collector;
如果你想要一个 12 个月的滚动总结,你不需要那么动态地构建数据透视表;您可以根据当前日期生成一个 month-offset 数字,这将为您提供一个固定范围的数值,您可以根据这些数值(而不是日期)进行调整,例如:
select * from (
select collector, low_activity_days,
months_between(trunc(sysdate, 'MM'), month) as month_offset
from low_activity_days_collect_t
where month >= add_months(trunc(sysdate, 'MM'), -13)
and month < trunc(sysdate, 'MM')
) src
pivot (sum(low_activity_days) as months_ago
for month_offset in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
这将给出列 collector
、1_months_ago
、2_months_ago
等
您不能轻易做到的是让列标题代表实际月份(例如 2017-04、2017-03 等),但您似乎并没有尝试这样做;并且除非您为旋转列术语设置别名,否则本示例中生成的术语必须被视为带引号的标识符(因为它们以数字开头)。
如果您确实想要月份 headers,您可以生成具有更多替换变量恶作剧的那些,在查询之前使用如下内容:
set termout off
column x_m1 new_value m1
column x_m2 new_value m2
...
column x_m12 new_value m12
select to_char(add_months(trunc(sysdate, 'MM'), -1), 'YYYY-MM') as x_m1,
to_char(add_months(trunc(sysdate, 'MM'), -2), 'YYYY-MM') as x_m2,
...
to_char(add_months(trunc(sysdate, 'MM'), -12), 'YYYY-MM') as x_m12
from dual;
column 1_months_ago heading &m1
column 2_months_ago heading &m2
...
column 12_months_ago heading &m12
set termout on
您可能会发现使用适当的报告工具更容易查询并 format/display 为您提供结果。
谁能告诉我如何才能完成这项工作?我得到 "ORA-56901: non-constant expression is not allowed for pivot|unpivot values" 或 "ORA-00917: missing comma" 取决于我是否在 IN 语句中将 &mb1 放在引号中。谢谢!
define mb1= ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1);
select *
from
( select COLLECTOR
,Month
,low_activity_days
from dwh_prod.low_activity_days_collect_t) src
pivot
(
sum(low_activity_days)
for month in ('&mb1')
) piv;
您可以改为将替换设置为固定值,这样它就不会尝试在数据透视子句中进行计算。当您处理日期时,您可以生成日期文字:
set termout off
column x_mb1 new_value mb1
select 'date ''' || TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1),
'YYYY-MM-DD') || '''' as x_mb1
from dual;
set termout on
select * from (
select COLLECTOR ,Month ,low_activity_days
from dwh_prod.low_activity_days_collect_t
) src
pivot ( sum(low_activity_days) for month in (&mb1) ) piv;
第一个查询 - 输出被 termout
隐藏生成一个字符串:
select 'date ''' || TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1),
'YYYY-MM-DD') || '''' as x_mb1
from dual;
X_MB1
-----------------
date '2017-03-01'
column ... new_value
command 然后将 &mb
设置为那个。然后,您真正查询中的替换变为:
select * from (
select COLLECTOR ,Month ,low_activity_days
from dwh_prod.low_activity_days_collect_t
) src
pivot ( sum(low_activity_days) for month in (date '2017-03-01') ) piv
您的原始代码的问题在于,您最终在替代主元句中引用了 sysdate
,这会引发 ORA-56901 异常(因为 sysdate
不是不变)。您可以在主元中使用任何固定值,因此您可以做:
define mb1=''01-APR-17''
... for month in (&mb1) ) piv;
将字符串周围的引号作为定义的一部分,或者
define mb1='01-APR-17'
... for month in ('&mb1') ) piv;
没有,或其他变化。但是因为这些最终都是字符串,所以你依赖于隐式日期转换,并且依赖于你的 NLS 设置;使用我生成的日期文字不是问题。如果你真的想使用那种日期格式,你仍然可以这样做:
define mb1='01-APR-17'
... for month in (to_date('&mb1', 'DD-MON-RR')) ) piv;
或 select 使用 new_values
方法的特定格式的日期:
column x_mb1 new_value mb1
select to_char(add_months(trunc(sysdate, 'MM'), -1), 'DD-MON-RR') as x_mb1 from dual;
... for month in (to_date('&mb1', 'DD-MON-RR')) ) piv;
不过,使用日期文字格式对我来说仍然更简单。
我不确定为什么旋转单个值特别有用。也许你真正的查询做的更多,但简单的聚合和过滤器在这里看起来更合适:
select collector, sum(low_activity_days)
from low_activity_days_collect_t
where month = add_months(trunc(sysdate, 'MM'), -1)
group by collector;
如果你想要一个 12 个月的滚动总结,你不需要那么动态地构建数据透视表;您可以根据当前日期生成一个 month-offset 数字,这将为您提供一个固定范围的数值,您可以根据这些数值(而不是日期)进行调整,例如:
select * from (
select collector, low_activity_days,
months_between(trunc(sysdate, 'MM'), month) as month_offset
from low_activity_days_collect_t
where month >= add_months(trunc(sysdate, 'MM'), -13)
and month < trunc(sysdate, 'MM')
) src
pivot (sum(low_activity_days) as months_ago
for month_offset in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
这将给出列 collector
、1_months_ago
、2_months_ago
等
您不能轻易做到的是让列标题代表实际月份(例如 2017-04、2017-03 等),但您似乎并没有尝试这样做;并且除非您为旋转列术语设置别名,否则本示例中生成的术语必须被视为带引号的标识符(因为它们以数字开头)。
如果您确实想要月份 headers,您可以生成具有更多替换变量恶作剧的那些,在查询之前使用如下内容:
set termout off
column x_m1 new_value m1
column x_m2 new_value m2
...
column x_m12 new_value m12
select to_char(add_months(trunc(sysdate, 'MM'), -1), 'YYYY-MM') as x_m1,
to_char(add_months(trunc(sysdate, 'MM'), -2), 'YYYY-MM') as x_m2,
...
to_char(add_months(trunc(sysdate, 'MM'), -12), 'YYYY-MM') as x_m12
from dual;
column 1_months_ago heading &m1
column 2_months_ago heading &m2
...
column 12_months_ago heading &m12
set termout on
您可能会发现使用适当的报告工具更容易查询并 format/display 为您提供结果。