Вы находитесь на странице: 1из 4

http://www.dba-oracle.com/t_display_multiple_column_values_same_rows.

htm Use a user-defined rowtocol function to convert the rows to columns:


CREATE OR REPLACE FUNCTION rowtocol( p_slct IN VARCHAR2, p_dlmtr IN VARCHAR2 DEFAULT ',' ) RETURN VARCHAR2 AUTHID CURRENT_USER AS TYPE c_refcur IS REF CURSOR; lc_str VARCHAR2(4000); lc_colval VARCHAR2(4000); c_dummy c_refcur; l number; BEGIN OPEN c_dummy FOR p_slct; LOOP FETCH c_dummy INTO lc_colval; EXIT WHEN c_dummy%NOTFOUND; lc_str := lc_str || p_dlmtr || lc_colval; END LOOP; CLOSE c_dummy; RETURN SUBSTR(lc_str,2); /* EXCEPTION WHEN OTHERS THEN lc_str := SQLERRM; IF c_dummy%ISOPEN THEN CLOSE c_dummy; END IF; RETURN lc_str; */ END; / SELECT DISTINCT

a.job, rowtocol( 'SELECT ename FROM emp WHERE job = ' || '''' || a.job || '''' || ' ORDER BY ename') AS Employees FROM emp a; /

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:15151874723724 sql> SELECT tr_date, item_id, adult_price adult, child_price child FROM mytable WHERE tr_date BETWEEN '01-jan-2004' AND '31-jan-2004' AND tr_code LIKE 'D%' The output is TR_DATE 06/01/2004 06/01/2004 11/01/2004 12/01/2004 12/01/2004 13/01/2004 13/01/2004 13/01/2004 Reqd. Output: The number of columns (item_id) depend on number of distinct item_id's returned by query Date/Itin_id 8 8 9 9 588 588 589 adult child adult child adult 06/01/2004 1189 832.3 1199 839.3 1249 07/01/2004 . . . . . . . 08/01/2004 . . . . . . . 10/01/2004 . . . . . . . 12/01/2004 . . . . . . . 13/01/2004 . . . . . . . ITEM_ID 8 9 7661 7659 7661 8 9 588 ADULT 1189 1199 849 759 849 959 1199 1249 CHILD 832.3 839.3 594.3 531.3 594.3 575.4 719.4 749.4

child 874.3

adult 1239

create or replace as type rc is ref procedure data end; / create or replace as

package pivot cursor; ( p_cursor in out rc ); package body pivot

procedure data( p_cursor in out rc ) is l_stmt long; begin l_stmt := 'select tr_date'; for x in ( select distinct item_id from t order by 1 ) loop l_stmt := l_stmt || ', max(decode(item_id,' || x.item_id || ', adult )) adult_' || x.item_id || ', max(decode(item_id,' || x.item_id || ', child )) child_' || x.item_id; end loop; l_stmt := l_stmt || ' from t group by tr_date order by tr_date'; end; end; / open p_cursor for l_stmt;

variable x refcursor set autoprint on exec pivot.data( :x );

http://forums.devshed.com/oracle-development-96/concatenating-multiplerows-of-a-column-into-one-169089.html
I have a table which looks as follows ID Name ----------1 ABC 1 DEF 1 GHI 2 JKL 2 MNO 2 PQR 2 STU 3 VW 3 XYZ I want to write a select statement which gives me the following ouput ID Names ----------------1 ABC-DEF-GHI 2 JKL-MNO-PQR-STU 3 VW-XYZ Is there a way this can be achieved by writing a SELECT statement and not PL/SQL code? If so, can some one please let me know. I appreciate your help Ans-01 The only way I could think of doing that is if you were able to loop through the contents of the table and check while the id's were equal, concatenate, otherwise go to the next one.

Ans-02
Unfortunately, there is no way to do this for the general case, without resort to a procedural function. If you desperately need a non-procedural solution, there is an "ugly" fix. The only criteria is that you need to know the MAXIMUM number of rows for the second column for each value in the first column. In your sample data, you can see that the value "2" in the first column has the largest number of second column entries (a total of 4). If 4 is always the largest number of column2 entries, the following query will work:
Code:

SELECT T1.C1, REPLACE(T1.C2 || '-' || NVL(T2.C2,' ') || '-' || NVL(T3.C2,' ') || '-' || NVL(T4.C2,' ') ,'- ',NULL) str FROM (SELECT c1, c2, row_number() over (PARTITION BY c1 ORDER BY c2) rn FROM tab) T1, (SELECT c1, c2, row_number() over (PARTITION BY c1 ORDER BY c2) rn FROM tab) T2, (SELECT c1, c2, row_number() over (PARTITION BY c1 ORDER BY c2) rn FROM tab) T3, (SELECT c1, c2, row_number() over (PARTITION BY c1 ORDER BY c2) rn FROM tab) T4 WHERE T1.RN = 1 AND T2.RN(+) = 2 AND T3.RN(+) = 3 AND T4.RN(+) = 4 AND T1.C1 = T2.C1(+) AND T1.C1 = T3.C1(+) AND T1.C1 = T4.C1(+)

(where tab is your sample table, and c1 and c2 are the two columns of tab). This can be expanded by simply adding and joining T5, T6, ... , TN, where "N" = "the largest number of values for c2 for any given c1".

######################################################

select e1.deptno, replace(e1.ename||', '||nvl(e2.ename,' ')|| ', ' || nvl(e3.ename,' ') ||', '|| nvl(e4.ename,''), ', ', NULL) Employees FROM (select deptno, ename, row_number() over (PARTITION BY deptno ORDER BY ename) rn FROM emp) (select deptno, ename, row_number() over (PARTITION BY deptno ORDER BY ename) rn FROM emp) (select deptno, ename, row_number() over (PARTITION BY deptno ORDER BY ename) rn FROM emp) (select deptno, ename, row_number() over (PARTITION BY deptno ORDER BY ename) rn FROM emp) WHERE e1.rn=1 and e2.rn(+)=2 and e3.rn(+)=3 and e4.rn(+)=4 and e1.deptno=e2.deptno(+) and e1.deptno=e3.deptno(+) and e1.deptno=e4.deptno(+)

e1, e2, e3, e4

Note: e4, e5,. The no. of select table will depends on (or equal to) = largest No. of values for ename for any given deptno

Вам также может понравиться