DB2 将解析函数限制为子查询

DB2 restrict analytic function to subselect

我经常遇到这样的情况,我想将分析函数(或 DB2 中的 OLAP)的操作限制为当前数据的某个子集。这是一个例子:

WITH MY_TABLE AS
(
     SELECT 1 AS FIELD1, 'A' AS FIELD2,  1 AS FIELD3, 'X' AS FIELD4 FROM DUAL
     UNION
     SELECT 1 AS FIELD1, 'A' AS FIELD2, 2 AS FIELD3, 'Y' AS FIELD4 FROM DUAL
     UNION
     SELECT 1 AS FIELD1, 'B' AS FIELD2, 3 AS FIELD3, 'X' AS FIELD4 FROM DUAL
     UNION
     SELECT 1 AS FIELD1, 'A' AS FIELD2, 4 AS FIELD3, 'Z' AS FIELD4 FROM DUAL
     UNION
     SELECT 1 AS FIELD1, 'B' AS FIELD2, 5 AS FIELD3, 'Z' AS FIELD4 FROM DUAL
     //...
)
SELECT FIRST_VALUE(FIELD4) OVER (PARTITION BY FIELD1 ORDER BY FIELD3) AS FIELD2_A
FROM MY_TABLE
WHERE FIELD2='A'  // need that as well for 'B', 'C' etc.

现在对 FIELD2 的所有必需值执行此操作很麻烦,然后再执行 JOIN 或 UNION,而且因为约束可能更复杂。

所以我真的很想一次处理它SELECT。这是一个试用版:

//...
SELECT CASE WHEN FIELD2 = 'A'
            THEN FIRST_VALUE(FIELD4)
                       OVER (PARTITION BY FIELD1
                             ORDER BY CASE WHEN FIELD2='A' THEN 0 ELSE 1 END, FIELD3)
            ELSE NULL END AS FIELD4_A,
       CASE WHEN FIELD2 = 'B'
            THEN FIRST_VALUE(FIELD4)
                       OVER (PARTITION BY FIELD1
                             ORDER BY CASE WHEN FIELD2='B' THEN 0 ELSE 1 END, FIELD3)
            ELSE NULL END AS FIELD4_B,
      //a bit more complicated 
      CASE WHEN FIELD2 IN ('A','C')
            THEN FIRST_VALUE(FIELD4)
                       OVER (PARTITION BY FIELD1
                             ORDER BY CASE WHEN FIELD2 IN ('A','C') THEN 0 ELSE 1 END, FIELD3)
            ELSE NULL END AS FIELD4_AC
FROM MY_TABLE

我们的想法是根据 WHERE 标准对数据集进行排序,但由于分区中可能不存在具有此类约束的行(因此会获得不需要的结果),因此非- 仅当 FIELD2 满足约束时才返回空值(这是在外部 CASE 语句中完成的)。

我猜这个方法可行(--我还没有测试过),但有点绕了路。 是否有更简单或更直接的方法来完成上述任务?

为什么这不是你想要的?

SELECT FIRST_VALUE(FIELD4) OVER (PARTITION BY FIELD1, FIELD2 ORDER BY FIELD3) AS FIELD2_A
FROM MY_TABLE

如果您希望将其旋转到单独的列中:

SELECT (CASE WHEN FIELD2 = 'A'
             THEN FIRST_VALUE(FIELD4) OVER (PARTITION BY FIELD1, FIELD2 ORDER BY FIELD3) 
        END) as FIELD4_A,
       (CASE WHEN FIELD2 = 'B'
             THEN FIRST_VALUE(FIELD4) OVER (PARTITION BY FIELD1, FIELD2 ORDER BY FIELD3) 
        END) as FIELD4_B,

编辑:

我怀疑您想要旋转 "first" 值。如果它永远不可能是 NULL,那么这可能就是您正在寻找的:

SELECT FIRST_VALUE(CASE WHEN FIELD2 = 'A' THEN FIELD4 END IGNORE NULLS) OVER
           (PARTITION BY FIELD1, FIELD2 ORDER BY FIELD3) as FIELD4_A,
       FIRST_VALUE(CASE WHEN FIELD2 = 'B' THEN FIELD4 END IGNORE NULLS) OVER
           (PARTITION BY FIELD1, FIELD2 ORDER BY FIELD3) as FIELD4_B,
. . .