【问题标题】:Oracle: replace "rollup" in query with something elseOracle:将查询中的“汇总”替换为其他内容
【发布时间】:2011-07-02 05:49:40
【问题描述】:

我需要重写一个没有汇总功能的简单查询。你能帮帮我吗?

这是一个原始查询:

  SELECT e.department_id, 
         e.job_id, 
         SUM(e.salary)
    FROM EMPLOYEES e
GROUP BY ROLLUP(e.department_id, e.job_id);

我猜可以使用 UNION 语句重写,是吗?

【问题讨论】:

  • 我的问题是我的电脑上没有安装 oracle,我无法“尝试”一些东西。
  • 那么您希望如何确定答案是否有效? Oracle Express 是免费的(目前是 10g,IIRC)。
  • @user628913:您可以在这里创建一个示例数据库,无需安装 Oracle 即可用于练习和运行查询:apex.oracle.com

标签: sql oracle rollup


【解决方案1】:

不需要 UNION,您可以使用 GROUPING SETS。这将产生相同的结果,甚至相同的解释计划:

  SELECT e.department_id, 
         e.job_id, 
         SUM(e.salary)
    FROM EMPLOYEES e
GROUP BY GROUPING SETS( (e.department_id, e.job_id), (e.department_id), () )

【讨论】:

    【解决方案2】:

    以下应该返回与汇总相同的结果,但性能更差,对“级别”的控制更少。

    select e.department_id
          ,e.job_id
          ,SUM(e.salary)
      from EMPLOYEES e
     group 
        by e.department_id
          ,e.job_id
    union all
    select e.department_id
          ,null
          ,SUM(e.salary)
      from EMPLOYEES e
     group 
        by e.department_id
    union all
    select null
          ,null
          ,SUM(e.salary)
      from EMPLOYEES e;
    

    【讨论】:

      【解决方案3】:

      您可以使用 CTE 来处理它(请注意,我通过 connect by 创建了 EMPLOYEE 表只是为了获取示例数据)。可能有更好的方法可以做到这一点,但这是一种方法!

      WITH EMPLOYEES AS(
          SELECT   MOD(LEVEL,5)  DEPARTMENT_ID 
                 , LEVEL JOB_ID 
                 , 1000*LEVEL SALARY
            FROM DUAL      
           CONNECT BY LEVEL < 10
      )
      , SUMMEDDATA AS(
        SELECT e.department_id, 
               e.job_id, 
               SUM(e.salary) SUMMED_SALARY
          FROM EMPLOYEES e
      GROUP BY e.department_id, e.job_id
      )
      , SUMMEDJOB_ID AS(
        SELECT e.department_id, 
               SUM(e.salary) SUMMED_SALARY
          FROM EMPLOYEES e
      GROUP BY e.department_id
      )
      , SUMMEDTOTAL AS(
        SELECT  
               SUM(e.salary) SUMMED_SALARY
          FROM EMPLOYEES e
      )
      SELECT DEPARTMENT_ID ,
             JOB_ID ,
             SUMMED_SALARY
        FROM SUMMEDDATA
      UNION ALL
      SELECT DEPARTMENT_ID ,
             NULL ,
             SUMMED_SALARY
        FROM SUMMEDJOB_ID
      UNION ALL
      SELECT NULL ,
             NULL ,
             SUMMED_SALARY
        FROM SUMMEDTOTAL
      ORDER BY 1 NULLS LAST, 2 NULLS LAST ;
      
      DEPARTMENT_ID          JOB_ID                 SUMMED_SALARY          
      ---------------------- ---------------------- ---------------------- 
      0                      5                      5000                   
      0                                             5000                   
      1                      1                      1000                   
      1                      6                      6000                   
      1                                             7000                   
      2                      2                      2000                   
      2                      7                      7000                   
      2                                             9000                   
      3                      3                      3000                   
      3                      8                      8000                   
      3                                             11000                  
      4                      4                      4000                   
      4                      9                      9000                   
      4                                             13000   
                                                    45000    
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-13
        • 2016-08-18
        • 2020-04-01
        相关资源
        最近更新 更多