مسعود سلطانی راد
مسعود سلطانی راد
خواندن ۲ دقیقه·۲ سال پیش

معرفی تابع LISTAGG در اوراکل و تجمیع رشته ها



مقدمه :

یکی از نیازمندی های همیشگی وقت با داده های پایگاه داده کار می کنیم، ساخت رشته ها ( عبارت ها) از تجمیع چند رشته (عبارت ) به عنوان خروجی می باشد. در این مستند در این خصوص صحبت خواهیم کرد و تابع کاربردی LISTAGG را معرفی خواهیم کرد.

به طور مثال مجموعه ای از افراد در دپارتمان های مختلف یک شرکت مشغول به کار هستند و حال مدیر مجموعه در خواست گزارشی دارد که در هر دپارتمان نام افراد در یک خط آورده شوند که در این صورت باید به ازای هر دپارتمان چند رکورد را در یک رکورد تجمیع کرد.

Base Data:

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

Desired Output:

DEPTNO EMPLOYEES

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

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

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

آماده سازی محیط تست :

--DROP TABLE emp PURGE;
CREATE TABLE emp (
empno    NUMBER(4) CONSTRAINT pk_emp PRIMARY KEY,
ename    VARCHAR2(10),
job      VARCHAR2(9),
mgr      NUMBER(4),
hiredate DATE,
sal      NUMBER(7,2),
comm     NUMBER(7,2),
deptno   NUMBER(2)
);
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,NULL,20);
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,NULL,20);
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);

برای اینکار می توان از راهکارهایی مانند ساخت تابع به وسیله خودمان استفاده کرد مانند نمونه کد زیر :

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;
/
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.

و استفاده از دیگر راهکارهایی مشابه تابع فوق.

تابع LISTAGG:

اوراکل در نسخه 11GR2 تابع 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.
آموزش اوراکلپایگاه داده اوراکلمشاوره اوراکلoracle listaggoracle database
چند سالی هست در حوزه داده ها ( نگهداری و تحلیل آنها) فعالیت دارم و همیشه سعی کردم آموخته هایم رو به اشتراک بگذارم soltanirad@artarad.ir www.artarad.ir
شاید از این پست‌ها خوشتان بیاید