天天看點

第二章   彙總和聚合資料(二)

 分多級聚合資料

    在Oracle中可以使用CUBE、ROLLUP和分組的功能來計算小計或其他聚合運算的中間結果。

以現實生活中的需求為例:計算按部門和工種分組後的平均薪水,合計薪水,然後是部門級别的平均薪水、合計薪水(不再考慮工種差別),最後是全公司範圍的平均與合計。

select department_id, job_id, avg(salary), sum(salary)
    from hr.employees
    group by rollup (department_id,job_id);      

    ROLLUP函數按照從右到左的順序,提供了向上彙集過程中不同級别的分組合計的功能。

    語句使用這樣的收起特性,相當于執行如下3條獨立語句,然後用UNION功能或應用層代碼把三條語句的結果合在一起。

select department_id , job_id , avg(salary) , sum(salary)
    from hr.employees
    group by department_id , job_id;
    select department_id , avg(salary) , sum(salary)
    from hr.employees
    group by department_id;
    select avg(salary) , sum(salary)
    from hr.employees;      

    細心的讀者會發現,因為ROLLUP函數是根據給定的字段由右到左收起的,當收起JOB_ID字段時,我們看到的是根據JOB_ID收起的彙總結果,但看不到原始資料根據DEPARTMENT_ID收起的彙總結果。我們可以用修改後的語句來改變這個結果:

select department_id, job_id, avg(salary), sum(salary)
    from hr.employees
    group by rollup (job_id,department_id);      

    執行這條語句,我們得到了DEPARTMENT_ID收起時的彙總結果,但又沒有了原始資料根據JOB_ID收起時的結果,我們隻能在最進階别(公司級别)的結果中看到JOB_ID的彙總結果,但二者意義不同。為了看到各個次元的收起結果,用CUBE函數重寫語句:

 select department_id , job_id , min(salary) , avg(salary) , max(salary)
    from hr.employees
    group by cube(department_id,job_id);      

    結果顯示了每個級别的收起彙總結果。

    ROLLUP和CUBE函數都可以包含我們希望的任意多的次元。再把例子擴充一下,還可以使用CUBE函數在部門,工種,經理和雇傭時間4個次元上計算平均薪水。

 select department_id,job_id,manager_id,
        extract(year from hire_date) as "START_YEAR",avg(salary)
    from hr.employee
    group by cube(department_id,job_id,manager_id,extract(year from hire_date));      

    語句的結果能提供4個次元上平均薪水的資料!

    Union與Union All 的比較

    有必要記住UNION與UNION ALL的差別。UNION會删除結果集中的重複資料(在去重複的時候對資料進行排序操作),UNION ALL則會保留源集中的所有資料,不管是否重複。

    nvl() 函數

    文法:NVL(eExpression1, eExpression2)