Da GROUP BY a OVER PARTITION
Sia data una tabella come la seguente, che descrive la struttura organizzativa di un'azienda.
I campi significativi per gli esempi di questo articolo sono i seguenti:
EMPNO: il codice personale del lavoratore
ENAME: il cognome del lavoratore
JOB: la mansione del lavoratore
MGR: il codice del responsabile del lavoratore
DEPTNO: il codice del dipartimento del lavoratore
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO----- ----- --- ---- --------- ---- ---- ------7369 SMITH CLERK 7902 17-DIC-80 800 207499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 307521 WARD SALESMAN 7698 22-FEB-81 1250 500 307566 JONES MANAGER 7839 02-APR-81 2975 207654 MARTIN SALESMAN 7698 28-SET-81 1250 1400 307698 BLAKE MANAGER 7839 01-MAG-81 2850 307782 CLARK MANAGER 7839 09-GIU-81 2450 107788 SCOTT ANALYST 7566 19-APR-87 3000 207839 KING PRESIDENT 17-NOV-81 5000 107844 TURNER SALESMAN 7698 08-SET-81 1500 0 307876 ADAMS CLERK 7788 23-MAG-87 1100 207900 JAMES CLERK 7698 03-DIC-81 950 307902 FORD ANALYST 7566 03-DIC-81 3000 207934 MILLER CLERK 7782 23-GEN-82 1300 10Supponiamo di volere rispondere alle seguenti domande:
1) quante righe ci sono per ogni tipo di mansione?
2a) quante righe ci sono per ogni dipartimento ?
2b) quante righe ci sono per ogni coppia: mansione, dipartimento ?
2c) quante righe ci sono per ogni tripla: mansione, dipartimento, responsabile ?
Le queries che rispondono alle suddette domande (sia in MySql che in Oracle) sono le seguenti:
1)
SELECT job, COUNT(*) CNT
FROM emp
GROUP BY job;
2a)
SELECT job, deptno, COUNT(*) CNT
FROM emp
GROUP BY job, deptno;
2b)
SELECT job, deptno, COUNT(*) CNT
FROM emp
GROUP BY job, deptno;
2c)
SELECT job, mgr, deptno, COUNT(*) CNT
FROM emp
GROUP BY job, mgr, deptno;
Nelle suddette query viene eseguito un conteggio (COUNT(*)) ed un raggruppamento (GROUP BY),
rispetto a due insiemi di campi: si noti che l'insieme dei campi elencati nella select deve essere
un sottoinsieme dell'insieme dei campi raggruppati dalla clausola GROUP BY.
Si noti inoltre che l'ordine in cui appaiono i campi raggruppati non é importante, così
al posto della query 2c) si può scrivere anche:
2c)
SELECT job, mgr, deptno, COUNT(*) CNT
FROM emp
GROUP BY deptno, job, mgr;
In sintesi, é un po' come se le query degli esempi suddetti "riducessero" tutte le righe della tabella,
raggruppandole appunto secondo i criteri specificati in ciascun caso.
Ora la domanda é: come si fa a ottenere la stessa informazione di conteggio e raggruppamento, ma senza ridurre
le righe?
In Oracle, questo é possibile con la clausola "COUNT(*) OVER (partition by ...)" .
Le query seguenti sono l'analogo delle query mostrate in precedenza, ma con il meccanismo di PARTITION al posto di GROUP BY.
1)
SELECT job, COUNT(*) OVER (partition by job) CNT
FROM emp;
2a)
SELECT deptno, COUNT(*) OVER (partition by deptno) CNT
FROM emp;
2b)
SELECT job, deptno, COUNT(*) OVER (partition by job, deptno) CNT
FROM emp;
2c)
SELECT job, mgr, deptno, COUNT(*) OVER (partition by job, mgr, deptno) CNT
FROM emp;
Il vantaggio di usare la clausola OVER é che in tal modo si può aggregare l'informazione senza usare la
clausola del raggruppamento, e ciò permette di mantenere, se necessario, tutte le righe della tabella.
CREDITS:
http://www.midnightdba.com/Jen/2010/10/tip-over-and-partition-by/
You have no rights to post comments