带条件的Oracle Query分组

时间:2018-10-11 02:25:54

标签: oracle

我有这样的查询结果:

DNAME           JOB       Total Empl    Average Sa
ACCOUNTING      CLERK           1       15600
ACCOUNTING      MANAGER         1       29400
ACCOUNTING      PRESIDENT       1       60000
ACCOUNTING      All Jobs        3       35000
RESEARCH        ANALYST         2       36000
RESEARCH        CLERK           2       11400
RESEARCH        MANAGER         1       35700
RESEARCH        All Jobs        5       26100
SALES           CLERK           1       11400
SALES           MANAGER         1       34200
SALES           SALESMAN        4       16800
SALES           All Jobs        6       18800
All Departments All Jobs        14      24878.5714

有可能变成这样吗?

DNAME           JOB       Total Empl   Average Sa
ACCOUNTING      CLERK           1       15600
                MANAGER         1       29400
                PRESIDENT       1       60000
                All Jobs        3       35000
RESEARCH        ANALYST         2       36000
                CLERK           2       11400
                MANAGER         1       35700
                All Jobs        5       26100
SALES           CLERK           1       11400
                MANAGER         1       34200
                SALESMAN        4       16800
                All Jobs        6       18800
All Departments All Jobs        14      24878.5714

我现有的查询:

SELECT 
DECODE(GROUPING(dname), 1, 'All Departments', dname) AS dname,
DECODE(GROUPING(job), 1, 'All Jobs', job) AS job,
COUNT(*) "Total Empl", AVG(sal) * 12 "Average Sal"
FROM emp, dept
WHERE dept.deptno = emp.deptno
GROUP BY ROLLUP (dname, job);

2 个答案:

答案 0 :(得分:0)

一种方法是将当前查询放入CTE中,然后仅当它是组中的第一条记录时才生成部门名称:

WITH cte AS (
    SELECT 
        DECODE(GROUPING(d.dname), 1, 'All Departments', d.dname) AS dname,
        DECODE(GROUPING(job), 1, 'All Jobs', job) AS job,
        COUNT(*) "Total Empl",
        AVG(sal) * 12 "Average Sal",
        ROW_NUMBER() OVER (PARTITION BY DECODE(GROUPING(d.dname), 1, 'All Departments', d.dname)
            ORDER BY DECODE(GROUPING(job), 1, 'All Jobs', job)) rn
    FROM emp e
    INNER JOIN dept d
        ON d.deptno = e.deptno
    GROUP BY ROLLUP (dname, job)
)

SELECT
    CASE WHEN rn = 1 THEN dname ELSE '' END AS dname,
    job,
    "Total Empl",
    "Average Sal"
FROM cte
ORDER BY
    dname,
    job;

虽然这可能符合您的期望,但通常最好在表示层中处理此类表示问题,例如类似于PHP。

答案 1 :(得分:0)

SQL * Plus之类的前端工具具有专门的功能,可以完全满足您的需求。

在SQL * Plus中,您只需要发出以下命令 ,然后按原样运行查询:

break on dname

如果在工作表上发出相同的BREAK命令(并执行该命令),然后执行“作为脚本”查询(“运行脚本”按钮),则可以在SQL Developer中执行相同的操作或F5)。

如果由于某种原因必须在一条SQL语句中完成所有操作,则这是一种方法。注意代码中的第三行-这是DECODE的最后一个参数。您没有看到两次-这是第二次(嵌套)对DECODE的调用。

SELECT 
DECODE(GROUPING(dname), 1, 'All Departments', 
  decode(job, min(job) over (partition by dname), dname) -- instead of just dname
) AS dname,
DECODE(GROUPING(job), 1, 'All Jobs', job) AS job,
COUNT(*) "Total Empl", AVG(sal) * 12 "Average Sal"
FROM scott.emp, scott.dept
WHERE dept.deptno = emp.deptno
 10  GROUP BY ROLLUP (dname, job);

DNAME           JOB       Total Empl Average Sal
--------------- --------- ---------- -----------
ACCOUNTING      CLERK              1       15600
                MANAGER            1       29400
                PRESIDENT          1       60000
                All Jobs           3       35000
RESEARCH        ANALYST            2       36000
                CLERK              2       11400
                MANAGER            1       35700
                All Jobs           5       26100
SALES           CLERK              1       11400
                MANAGER            1       34200
                SALESMAN           4       16800
                All Jobs           6       18800
All Departments All Jobs          14  24878.5714