简体   繁体   English

Oracle SQL - 获取每列的最新值

[英]Oracle SQL - Get latest value of each column

Suppose I have a table that looks like this:假设我有一个看起来像这样的表:

样品表

There are 2 ISIN's in the table (ISIN 1 and 2).表中有 2 个 ISIN(ISIN 1 和 2)。 If you look at the first row, you'll see that all fields are filled with values.如果您查看第一行,您会看到所有字段都填满了值。 In the second row there is only one field filled, which represents an update of the field (all empty fields didn't changed).在第二行中只有一个字段被填充,代表该字段的更新(所有空字段都没有改变)。

Basically I want the latest value of each field (grouped by ISIN).基本上我想要每个字段的最新值(按 ISIN 分组)。

结果

I was thinking of creating a Materialized view, if there is a build-in function or an easy way to achive my result.如果有内置的 function 或实现我的结果的简单方法,我正在考虑创建一个物化视图。 If there is not, I'll create a pipe function and iterate over the records.如果没有,我将创建一个 pipe function 并遍历记录。

You can use the LAST_VALUE analytic function:您可以使用LAST_VALUE解析 function:

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

or, you can use MAX()... KEEP ( DENSE_RANK... ) :或者,您可以使用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

Which, for the sample data:其中,对于示例数据:

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;

Both output:两者都是 output:

 TS | TS | ID |编号 | ISIN |伊斯坦布尔 | VALUE1 | VALUE1 | VALUE2 | VALUE2 | VALUE3 | VALUE3 | VALUE4 | VALUE4 | VALUE5 | VALUE5 | VALUE6:-------- |值 6:-------- | -: | -: | ---: |:----- |:----- |:----- |:----- |:----- |:----- 09-NOV-20 | ---: |:----- |:----- |:----- |:----- |:----- |:----- 11 月 9 日- 20 | 4 | 4 | 1 | 1 | A |一个 | H | H | G |格 | J |杰| I |我 | F 11-NOV-20 |女 20 年 11 月 11 日 | 7 | 7 | 2 | 2 | K | K | Q |问 | M |男| R | R | O |欧 | P P

db<>fiddle here db<> 在这里摆弄

This is it:就是这个:

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";

check: http://sqlfiddle.com/#!4/f02bd/5检查: http://sqlfiddle.com/#!4/f02bd/5

You can use the KEEP clause as follows:您可以按如下方式使用 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM