簡體   English   中英

如何在Oracle中將多行合並為單行

[英]How to merge multiple rows into single in Oracle

我正在尋找將多行合並為單行的想法

可以說我有這樣的表:

ID |  A  |  B  |  C  |  D  |
____________________________
 1 |  x  |  y  |null |  z  |
 2 |null |  z  |null |  x  |
 3 | p   |  w  | a   |null |
 4 | o   |null | k   |null |

現在我需要將具有較低ID的所有行的更改應用於每一行。 第一行是一個基礎所以它應該看起來:

1 |  x  |  y  |null |  z  |

現在,對於第二行,我需要從第一行開始並從第二行應用更改(如果列不為空)。 第二行應該是這樣的:

2 |  x  |  z  |null |  x  |

第三行 - 從第一行開始,從第二行和第三行應用更改:

3 |  p  |  w  |  a  |  x  |

第四行 - 取第一行,應用第二行,第三行和第四行:

4 |  o  |  w  |  k  |  x  | 

所以輸出應該是這樣的:

1 |  x  |  y  |null |  z  |
2 |  x  |  z  |null |  x  |
3 |  p  |  w  |  a  |  x  |
4 |  o  |  w  |  k  |  x  | 

是否有可用於此的Oracle功能?

您可以使用last_value()函數 ,使用ignore nulls last_value()選項:

last_value(a) ignore nulls over (order by id)

將為您提供在a列中看到的最后一個非空值,直到當前ID(使用默認窗口); 所以你可以為你想要“合並”的每一列重復這個:

select id,
  last_value(a) ignore nulls over (order by id) as a,
  last_value(b) ignore nulls over (order by id) as b,
  last_value(c) ignore nulls over (order by id) as c,
  last_value(d) ignore nulls over (order by id) as d
from your_table
order by id;

將您的樣本數據作為CTE:

with your_table (id,  a,  b,  c,  d) as (
            select 1, 'x', 'y', null, 'z' from dual
  union all select 2, null, 'z', null,'x' from dual
  union all select 3, 'p', 'w', 'a', null from dual
  union all select 4, 'o', null, 'k', null from dual
)
select id,
  last_value(a) ignore nulls over (order by id) as a,
  last_value(b) ignore nulls over (order by id) as b,
  last_value(c) ignore nulls over (order by id) as c,
  last_value(d) ignore nulls over (order by id) as d
from your_table
order by id;

        ID A B C D
---------- - - - -
         1 x y   z
         2 x z   x
         3 p w a x
         4 o w k x

使用層次查詢:

CREATE TABLE abcd(
  id int,
   A  varchar2(10),
   B varchar2(10),  
   C varchar2(10),  D varchar2(10)
);

insert all
  into abcd values(1,'x','y',null,'z')
  into abcd values(2,null,'z',null,'x')
  into abcd values(3,'p','w','a',null)
  into abcd values(4,'o',null,'k',null)
select 1 from dual;

commit;

WITH qq(id, a,b,c,d) AS(
   SELECT id, a,b,c,d FROM abcd WHERE id = 1
   UNION ALL
   SELECT x.id, 
          coalesce( x.a, qq.a ),
          coalesce( x.b, qq.b ),
          coalesce( x.c, qq.c ),
          coalesce( x.d, qq.d )
   FROM qq
   JOIN abcd x ON x.id = qq.id + 1
)
SELECT * FROM qq;

       ID A          B          C          D         
---------- ---------- ---------- ---------- ----------
         1 x          y                     z         
         2 x          z                     x         
         3 p          w          a          x         
         4 o          w          k          x         

LAST_VALUE類似,您也可以使用COALESCELAG

Oracle安裝程序

一個小的PL / SQL腳本,用於創建具有預定義列數的表,並使用10行隨機數據填充該行,該行有50%的機會為NULL

--DROP TABLE table_name;
--DROP SEQUENCE table_name_seq;
SET SERVEROUTPUT ON;
DECLARE
  num_columns INT := 5;
  ct  CLOB := 'CREATE TABLE table_name ( id INT';
  ins CLOB := 'INSERT INTO table_name VALUES ( table_name_seq.nextval';
  val CLOB := 'SELECT id';
BEGIN
  FOR i IN 1 .. num_columns LOOP
    ct  := ct || ', c' || TO_CHAR( i, 'FM00' ) || ' INT';
    ins := ins || ',' || CHR(10) || '  CASE WHEN DBMS_RANDOM.VALUE < .5 THEN NULL ELSE TRUNC( DBMS_RANDOM.VALUE( 0, 100 ) ) END';
    val := val || ',' || CHR(10) || '       COALESCE( c' || TO_CHAR( i, 'FM00' ) || ', LAG( c' || TO_CHAR( i, 'FM00' ) || ' ) IGNORE NULLS OVER ( ORDER BY id ) ) AS c' || TO_CHAR( i, 'FM00' );
  END LOOP;
  ct  := ct || ' )';
  ins := ins || ' )';
  val := val || CHR(10) || 'FROM   table_name;';
  EXECUTE IMMEDIATE ct;
  EXECUTE IMMEDIATE 'CREATE SEQUENCE table_name_seq';
  FOR i IN 1 .. 10 LOOP
    EXECUTE IMMEDIATE ins;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE( val );
END;
/

查詢1

SELECT * FROM table_name;

結果

        ID        C01        C02        C03        C04        C05
---------- ---------- ---------- ---------- ---------- ----------
         1                                                       
         2         37         82         85                    21
         3          8                               76         55
         4         98                    66         78           
         5         17                    39                    19
         6         17          3         91                      
         7         76                    42         63         19
         8         18                    95                      
         9         88         24         49                      
        10                    51                    81         49

查詢2

SELECT id,
       COALESCE( c01, LAG( c01 ) IGNORE NULLS OVER ( ORDER BY id ) ) AS c01,
       COALESCE( c02, LAG( c02 ) IGNORE NULLS OVER ( ORDER BY id ) ) AS c02,
       COALESCE( c03, LAG( c03 ) IGNORE NULLS OVER ( ORDER BY id ) ) AS c03,
       COALESCE( c04, LAG( c04 ) IGNORE NULLS OVER ( ORDER BY id ) ) AS c04,
       COALESCE( c05, LAG( c05 ) IGNORE NULLS OVER ( ORDER BY id ) ) AS c05
FROM   table_name;

結果

        ID        C01        C02        C03        C04        C05
---------- ---------- ---------- ---------- ---------- ----------
         1                                                       
         2         37         82         85                    21
         3          8         82         85         76         55
         4         98         82         66         78         55
         5         17         82         39         78         19
         6         17          3         91         78         19
         7         76          3         42         63         19
         8         18          3         95         63         19
         9         88         24         49         63         19
        10         88         51         49         81         49

num_columns值更改為99,您可以看到它在具有100個值的表上工作,沒有任何問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM