假设我有一个像这样的表:
表中有2个ISIN(ISIN 1和2)。如果查看第一行,将会看到所有字段都填充了值。在第二行中,仅填充了一个字段,代表该字段的更新(所有空白字段均未更改)。
基本上我想要每个字段的最新值(按ISIN分组)。
我想创建一个物化视图,如果有内置功能或简单的方法来获得结果。如果没有,我将创建管道函数并遍历记录。
答案 0 :(得分:1)
您可以使用LAST_VALUE
分析函数:
SELECT ts,
id,
isin,
value1,
value2,
value3,
value4,
value5,
value6
FROM (
SELECT ts,
id,
isin,
LAST_VALUE(value1) IGNORE NULLS OVER ( PARTITION BY isin ORDER BY ts, id ) AS value1,
LAST_VALUE(value2) IGNORE NULLS OVER ( PARTITION BY isin ORDER BY ts, id ) AS value2,
LAST_VALUE(value3) IGNORE NULLS OVER ( PARTITION BY isin ORDER BY ts, id ) AS value3,
LAST_VALUE(value4) IGNORE NULLS OVER ( PARTITION BY isin ORDER BY ts, id ) AS value4,
LAST_VALUE(value5) IGNORE NULLS OVER ( PARTITION BY isin ORDER BY ts, id ) AS value5,
LAST_VALUE(value6) IGNORE NULLS OVER ( PARTITION BY isin ORDER BY ts, id ) AS value6,
ROW_NUMBER() OVER ( PARTITION BY isin ORDER BY ts DESC, id DESC ) AS rn
FROM table_name
)
WHERE rn = 1
或者,您可以使用MAX() ... KEEP ( DENSE_RANK ... )
:
SELECT MAX(ts) AS ts,
MAX(id) KEEP ( DENSE_RANK LAST ORDER BY ts, id ) AS id,
isin,
MAX(value1) KEEP (
DENSE_RANK FIRST
ORDER BY
CASE WHEN value1 IS NOT NULL THEN ts END DESC NULLS LAST,
id DESC
) AS value1,
MAX(value2) KEEP (
DENSE_RANK FIRST
ORDER BY
CASE WHEN value2 IS NOT NULL THEN ts END DESC NULLS LAST,
id DESC
) AS value2,
MAX(value3) KEEP (
DENSE_RANK FIRST
ORDER BY
CASE WHEN value3 IS NOT NULL THEN ts END DESC NULLS LAST,
id DESC
) AS value3,
MAX(value4) KEEP (
DENSE_RANK FIRST
ORDER BY
CASE WHEN value4 IS NOT NULL THEN ts END DESC NULLS LAST,
id DESC
) AS value4,
MAX(value5) KEEP (
DENSE_RANK FIRST
ORDER BY
CASE WHEN value5 IS NOT NULL THEN ts END DESC NULLS LAST,
id DESC
) AS value5,
MAX(value6) KEEP (
DENSE_RANK FIRST
ORDER BY
CASE WHEN value6 IS NOT NULL THEN ts END DESC NULLS LAST,
id DESC
) AS value6
FROM table_name
GROUP BY isin
其中的示例数据:
CREATE TABLE table_name ( ts, id, isin, value1, value2, value3, value4, value5, value6 ) AS
SELECT SYSDATE - 5, 1, 1, 'A', 'B', 'C', 'D', 'E', 'F' FROM DUAL UNION ALL
SELECT SYSDATE - 4, 2, 1, NULL, NULL, 'G', NULL, NULL, NULL FROM DUAL UNION ALL
SELECT SYSDATE - 3, 3, 1, NULL, 'H', NULL, NULL, 'I', NULL FROM DUAL UNION ALL
SELECT SYSDATE - 2, 4, 1, NULL, NULL, NULL, 'J', NULL, NULL FROM DUAL UNION ALL
SELECT SYSDATE - 2, 5, 2, 'K', 'L', 'M', 'N', 'O', 'P' FROM DUAL UNION ALL
SELECT SYSDATE - 1, 6, 2, NULL, 'Q', NULL, NULL, NULL, NULL FROM DUAL UNION ALL
SELECT SYSDATE - 0, 7, 2, NULL, NULL, NULL, 'R', NULL, NULL FROM DUAL;
两个输出:
TS | ID | ISIN | VALUE1 | VALUE2 | VALUE3 | VALUE4 | VALUE5 | VALUE6 :-------- | -: | ---: | :----- | :----- | :----- | :----- | :----- | :----- 09-NOV-20 | 4 | 1 | A | H | G | J | I | F 11-NOV-20 | 7 | 2 | K | Q | M | R | O | P
db <>提琴here
答案 1 :(得分:1)
就这样:
SELECT SUBSTR(LISTAGG("col1" ,', ') WITHIN GROUP (ORDER BY "col1"),-1,1)as value1,
SUBSTR(LISTAGG("col2" ,', ') WITHIN GROUP (ORDER BY "col2"),-1,1)as value2,
SUBSTR(LISTAGG("col3" ,', ') WITHIN GROUP (ORDER BY "col3"),-1,1)as value3,
SUBSTR(LISTAGG("col4" ,', ') WITHIN GROUP (ORDER BY "col4"),-1,1)as value4,
SUBSTR(LISTAGG("col5" ,', ') WITHIN GROUP (ORDER BY "col5"),-1,1)as value5,
SUBSTR(LISTAGG("col6" ,', ') WITHIN GROUP (ORDER BY "col6"),-1,1)as value6
FROM Table1
group by "isin";
答案 2 :(得分:0)
您可以按以下方式使用KEEP子句:
SELECT ISIN,
MAX(VALUE1) KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN VALUE1 IS NULL THEN NULL ELSE "TIMESTAMP" END DESC NULLS LAST) AS VALUE1,
MAX(VALUE2) KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN VALUE2 IS NULL THEN NULL ELSE "TIMESTAMP" END DESC NULLS LAST) AS VALUE2,
...
FROM YOUR_TABLE
GROUP BY ISIN;