日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

oracle一行变一列,oracle多行变一行

發布時間:2025/3/19 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oracle一行变一列,oracle多行变一行 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天遇到將多行轉為一行的一個操作,多謝oracle開發板的 wildwave 提供了比較通用的解決辦法,同時也將自己搜到的這方面資料整理如下,多是用于連接列值的。

String集聚連接技術

需要將多行轉換為一行,例子如下:

基礎數據:

DEPTNO ENAME

---------- ----------

20 SMITH

30 ALLEN

30 WARD

20 JONES

30 MARTIN

30 BLAKE

10 CLARK

20 SCOTT

10 KING

30 TURNER

20 ADAMS

30 JAMES

20 FORD

10 MILLER

預期輸出:

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

* LISTAGG分析函數(11g Release 2)

* WM_CONCAT內建函數

* 自定義函數

* 使用Ref Cursor實現通用函數

* 用戶自定義聚集函數

* ROW_NUMBER()和SYS_CONNECT_BY_PATH函數(Oracle 9i)

* COLLECT函數(Oracle 10g)

LISTAGG分析函數(11g Release 2)

Oracle 11g Release 2介紹了LISTAGG 函數,使得聚集連接字符串變得很容易。并且允許使用我們指定連接串中的字段順序。使用LISTAGG如下:

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees

FROM?? emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 ADAMS,FORD,JONES,SCOTT,SMITH

30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

WM_CONCAT內建函數

如果你的Oracle不是11g Release 2,但是支持WM_CONCAT函數,那么解決上面的問題同樣是小菜一碟,使用WM_CONCAT 函數G如下:

COLUMN employees FORMAT A50

SELECT deptno, wm_concat(ename) AS employees

FROM?? emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

3 rows selected.

自定義函數

另一個方法是自定義一個函數解決問題。get_employees對于給定部門返回一組員工:

CREATE OR REPLACE FUNCTION get_employees (p_deptno? in? emp.deptno%TYPE)

RETURN VARCHAR2

IS

l_text? VARCHAR2(32767) := NULL;

BEGIN

FOR cur_rec IN (SELECT ename FROM emp WHERE deptno = p_deptno) LOOP

l_text := l_text || ',' || cur_rec.ename;

END LOOP;

RETURN LTRIM(l_text, ',');

END;

/

SHOW ERRORS

COLUMN employees FORMAT A50

SELECT deptno,

get_employees(deptno) AS employees

FROM?? emp

GROUP by deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

為了改善性能減少函數調用,我們預先過濾行數。.

COLUMN employees FORMAT A50

SELECT e.deptno,

get_employees(e.deptno) AS employees

FROM?? (SELECT DISTINCT deptno

FROM?? emp) e;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

使用Ref Cursor實現通用函數

另一個可替代的方法是使用游標變量寫一個函數來連接行值?;竞蜕厦嬉粯?#xff0c;只是傳入的是一個游標,所以使得它更通用:.

CREATE OR REPLACE FUNCTION concatenate_list (p_cursor IN? SYS_REFCURSOR)

RETURN? VARCHAR2

IS

l_return? VARCHAR2(32767);

l_temp??? VARCHAR2(32767);

BEGIN

LOOP

FETCH p_cursor

INTO? l_temp;

EXIT WHEN p_cursor%NOTFOUND;

l_return := l_return || ',' || l_temp;

END LOOP;

RETURN LTRIM(l_return, ',');

END;

/

SHOW ERRORS

使用如下:

COLUMN employees FORMAT A50

SELECT e1.deptno,

concatenate_list(CURSOR(SELECT e2.ename FROM emp e2 WHERE e2.deptno = e1.deptno)) employees

FROM?? emp e1

GROUP BY e1.deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

同樣的,為了減少函數調用可以預先顧慮一些行。.

COLUMN employees FORMAT A50

SELECT deptno,

concatenate_list(CURSOR(SELECT e2.ename FROM emp e2 WHERE e2.deptno = e1.deptno)) employees

FROM?? (SELECT DISTINCT deptno

FROM emp) e1;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

用戶自定義聚集函數

如果你不想使用內置的函數,你可以自定義聚集函數:

CREATE OR REPLACE TYPE t_string_agg AS OBJECT

(

g_string? VARCHAR2(32767),

STATIC FUNCTION ODCIAggregateInitialize(sctx? IN OUT? t_string_agg)

RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate(self?? IN OUT? t_string_agg,

value? IN????? VARCHAR2 )

RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateTerminate(self???????? IN?? t_string_agg,

returnValue? OUT? VARCHAR2,

flags??????? IN?? NUMBER)

RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge(self? IN OUT? t_string_agg,

ctx2? IN????? t_string_agg)

RETURN NUMBER

);

/

SHOW ERRORS

CREATE OR REPLACE TYPE BODY t_string_agg IS

STATIC FUNCTION ODCIAggregateInitialize(sctx? IN OUT? t_string_agg)

RETURN NUMBER IS

BEGIN

sctx := t_string_agg(NULL);

RETURN ODCIConst.Success;

END;

MEMBER FUNCTION ODCIAggregateIterate(self?? IN OUT? t_string_agg,

value? IN????? VARCHAR2 )

RETURN NUMBER IS

BEGIN

SELF.g_string := self.g_string || ',' || value;

RETURN ODCIConst.Success;

END;

MEMBER FUNCTION ODCIAggregateTerminate(self???????? IN?? t_string_agg,

returnValue? OUT? VARCHAR2,

flags??????? IN?? NUMBER)

RETURN NUMBER IS

BEGIN

returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');

RETURN ODCIConst.Success;

END;

MEMBER FUNCTION ODCIAggregateMerge(self? IN OUT? t_string_agg,

ctx2? IN????? t_string_agg)

RETURN NUMBER IS

BEGIN

SELF.g_string := SELF.g_string || ',' || ctx2.g_string;

RETURN ODCIConst.Success;

END;

END;

/

SHOW ERRORS

CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)

RETURN VARCHAR2

PARALLEL_ENABLE AGGREGATE USING t_string_agg;

/

SHOW ERRORS

使用如下:

COLUMN employees FORMAT A50

SELECT deptno, string_agg(ename) AS employees

FROM?? emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

3 rows selected.

ROW_NUMBER()和SYS_CONNECT_BY_PATH函數(Oracle 9i)

使用 ROW_NUMBER() 和SYS_CONNECT_BY_PATH 實現:

SELECT deptno,

LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))

KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees

FROM?? (SELECT deptno,

ename,

ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,

ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev

FROM?? emp)

GROUP BY deptno

CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno

START WITH curr = 1;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 ADAMS,FORD,JONES,SCOTT,SMITH

30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

COLLECT函數(Oracle 10g)

使用COLLECT函數,這個需要一個關聯數組:

CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000);

/

CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab? IN? t_varchar2_tab,

p_delimiter???? IN? VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS

l_string???? VARCHAR2(32767);

BEGIN

FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP

IF i != p_varchar2_tab.FIRST THEN

l_string := l_string || p_delimiter;

END IF;

l_string := l_string || p_varchar2_tab(i);

END LOOP;

RETURN l_string;

END tab_to_string;

/

使用如下:

COLUMN employees FORMAT A50

SELECT deptno,

tab_to_string(CAST(COLLECT(ename) AS t_varchar2_tab)) AS employees

FROM?? emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的oracle一行变一列,oracle多行变一行的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。