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,
. . .
我经常遇到这样的情况,我想将分析函数(或 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,
. . .