使用 IndexCol 函数

在 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 函数用于更改可视化中的期间粒度:

  1. 创建一个参数以用作列选择器来选择期间粒度,在此示例中为 Month 或 Quarter。

    GUID-1141C5E4-DB56-49D1-94EB-3010D274C477-default.jpg 的说明如下
    .jpg 的说明

  2. 创建一个定制计算来执行 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")

    GUID-1EBB2C95-3D23-48C6-9754-EF968AFAFE98-default.jpg 的说明如下
    .jpg 的说明

  3. 将该参数添加到工作簿的筛选器栏中。然后,用户可以通过从列选择器筛选器中选择 MonthQuarter 来更改报表的粒度。

    GUID-C1469E54-1C7D-4FDF-B3E6-CCFE73BF2A32-default.jpg 的说明如下
    .jpg 的说明