在 Oracle Analytics 中,计算根据变量值分支时通常会使用 CASE
语句。在 CASE
语句中引用变量时,优先使用 IndexCol
函数以提高生成的 SQL 代码的效率。本主题介绍 IndexCol
函数以及何时使用它。
关于 IndexCol 函数
在计算中的列或值根据会话、资料档案库或表示变量的值变化时,使用 IndexCol
函数。
IndexCol
函数的语法如下:
INDEXCOL(<<integer_literal>>, <<expr_list>>)
其中,第一个参数解析为整数,组成 <<expr_list>>
的项对应于第一个参数的可能值的数量。将在 SQL 语句中根据第一个参数的值使用这些项之一。
例如,如果 <<integer_literal>>
参数有三个可能值,则 <<expr_list>>
参数中必须有三个参数,<<integer_literal>>
的每个可能值对应一个。
第一个参数通常基于会话变量的值或引用变量的 CASE
语句。可以在资料档案库 (RPD) 文件中或直接在报表列中对 IndexCol
函数建模。您可以嵌套多个 IndexCol
函数以组成单个语句。
IndexCol 函数的好处
使用 <<case when>>
语句的计算将完整推送到物理 SQL 代码。相比之下,IndexCol
函数仅将所需列或表达式推送到数据库。这是因为 IndexCol
函数是在物理 SQL 代码生成之前求值。
在与变量提示(允许在值列表中选择值)结合使用时,您可以对报表结构进行大幅修改,而不会给性能带来任何负面影响。
IndexCol
函数的一个缺点是不能在整数计算中将其与 like
一起使用,而在表达式列表中可以使用 like
。如果整数计算需要 like
,则必须改用 CASE
语句。
示例
假定存在名为 PREFERRED_CURRENCY
的会话变量,用于设置用户的首选货币。然后,根据会话变量的值,以用户指定的货币显示收入。
创建了两个计算,以根据该会话变量的值返回正确货币。
第一个计算使用 CASE
语句,如以下所示:
CASE WHEN VALUEOF("NQ_SESSION"."PREFERRED_CURRENCY") = 'USD' THEN "01 - Sample App Data (ORCL)".""."BISAMPLE"."F19 Rev. (Converted)"."Revenue_Usd" WHEN VALUEOF("NQ_SESSION"."PREFERRED_CURRENCY") = 'EUR' THEN "01 - Sample App Data (ORCL)".""."BISAMPLE"."F19 Rev. (Converted)"."Revenue_Eur" WHEN VALUEOF("NQ_SESSION"."PREFERRED_CURRENCY") = 'AUD' THEN "01 - Sample App Data (ORCL)".""."BISAMPLE"."F19 Rev. (Converted)"."Revenue_Aud" ELSE NULL END
第二个计算使用 IndexCol
函数,如下所示:
INDEXCOL( CASE VALUEOF("NQ_SESSION"."PREFERRED_CURRENCY") WHEN 'USD' THEN 0 WHEN 'EUR' THEN 1 WHEN 'AUD' THEN 2 END , "01 - Sample App Data (ORCL)".""."BISAMPLE"."F19 Rev. (Converted)"."Revenue_Usd", "01 - Sample App Data (ORCL)".""."BISAMPLE"."F19 Rev. (Converted)"."Revenue_Eur", "01 - Sample App Data (ORCL)".""."BISAMPLE"."F19 Rev. (Converted)"."Revenue_Aud")
由于 IndexCol
函数的第一个参数必须解析为整数,因此使用了 CASE
语句进行解析。
使用 CASE
语句计算运行查询时,整个 CASE
语句将推送到数据库,因为 CASE
语句是在运行时求值。在某些情况下,这可能会导致优化程序出现问题。
WITH SAWITH0 AS (select sum(case when 'USD' = 'USD' then T42437.Revenue_Usd when 'EUR' = 'USD' then T42437.Revenue_Eur when 'AUD' = 'USD' then T42437.Revenue_Aud else NULL end ) as c1, T42412.Office_Dsc as c2, T42412.Office_Key as c3 from BISAMPLE.SAMP_OFFICES_D T42412 /* D30 Offices */ , BISAMPLE.SAMP_REVENUE_CURR_F T42437 /* F19 Rev. (Converted) */ where ( T42412.Office_Key = T42437.Office_Key ) group by T42412.Office_Dsc, T42412.Office_Key), SAWITH1 AS (select 0 as c1, D1.c2 as c2, D1.c1 as c3, D1.c3 as c4 from SAWITH0 D1) select D1.c1 as c1, D1.c2 as c2, D1.c3 as c3 from ( select D1.c1 as c1, D1.c2 as c2, D1.c3 as c3 from SAWITH1 D1 order by c2 ) D1 The same query run using the IndexCol function pushes down only the expression needed to satisfy the query, because the IndexCol function is resolved prior to SQL generation. This helps avoid issues with the Optimizer. WITH SAWITH0 AS (select sum(T42437.Revenue_Usd) as c1, T42412.Office_Dsc as c2, T42412.Office_Key as c3 from BISAMPLE.SAMP_OFFICES_D T42412 /* D30 Offices */ , BISAMPLE.SAMP_REVENUE_CURR_F T42437 /* F19 Rev. (Converted) */ where ( T42412.Office_Key = T42437.Office_Key ) group by T42412.Office_Dsc, T42412.Office_Key), SAWITH1 AS (select 0 as c1, D1.c2 as c2, D1.c1 as c3, D1.c3 as c4 from SAWITH0 D1) select D1.c1 as c1, D1.c2 as c2, D1.c3 as c3 from ( select D1.c1 as c1, D1.c2 as c2, D1.c3 as c3 from SAWITH1 D1 order by c2 ) D1
工作簿和 IndexCol
可以在工作簿中使用 IndexCol
函数。
在此示例中,IndexCol
函数用于更改可视化中的期间粒度:
IndexCol
函数。该计算如下:
indexcol(case when @parameter("Time Selector Value")('Month')='Month' then 0 else 1 end, "HCM - Workforce Core"."Time"."Month Name", "HCM - Workforce Core"."Time"."Quarter")