【问题标题】:Oracle SQL grouping set returning more than one rowOracle SQL 分组集返回多于一行
【发布时间】:2016-03-11 11:09:24
【问题描述】:

我正在编写一个 Oracle sql 脚本,该脚本显示一个部门位置 (location_id = 1700) 与 所有其他 部门位置 (location_id <> 1700) 的平均值 - 因为它比较两个值,我希望只返回两行。我能够像这样计算出一个查询:

select d.LOCATION_ID, round(avg(e.salary),2) AS "AVG SALARY", count(d.LOCATION_ID) from departments d
join employees e on e.DEPARTMENT_ID = d.DEPARTMENT_ID
where d.location_id = 1700
group by grouping sets(d.LOCATION_ID);

这会为我返回一行:

我的第二个查询返回四行而不是单行(就像我想的那样):

select round(avg(e.salary),2) AS "AVG SALARY", count(d.LOCATION_ID) from departments d
join employees e on e.DEPARTMENT_ID = d.DEPARTMENT_ID
where d.location_id <> 1700
group by grouping sets(d.LOCATION_ID);

这会返回 4 行,但我希望它只返回 1 行:

我希望解决两个查询,然后将它们合并在一起——显然我需要克服第二个查询的障碍,然后再将它们合并在一起。
有什么想法吗?

【问题讨论】:

    标签: sql oracle oracle11g group-by


    【解决方案1】:

    尝试完全删除 group bys。听起来您只需要平均 where location_id = 1700 和 where location_id 1700 然后 UNION 这两个结果。

    select '1700' as "LOCATION", round(avg(e.salary),2) AS "AVG SALARY", count(d.LOCATION_ID) as "COUNT"
    from departments d
    join employees e on e.DEPARTMENT_ID = d.DEPARTMENT_ID
    where d.location_id = 1700
    
    union
    
    select '<>1700' as "LOCATION", round(avg(e.salary),2) AS "AVG SALARY", count(d.LOCATION_ID) as "COUNT"
    from departments d
    join employees e on e.DEPARTMENT_ID = d.DEPARTMENT_ID
    where d.location_id <> 1700
    

    【讨论】:

    • 谢谢,我是在用group by 声明来装逼自己
    【解决方案2】:

    location_id 应包含在第二个查询的 select 中。现在您可以使用union all 组合结果集。

    select d.location_id, round(avg(e.salary),2) AS "AVG SALARY", count(d.LOCATION_ID) 
    from departments d
    join employees e on e.DEPARTMENT_ID = d.DEPARTMENT_ID
    where d.location_id <> 1700
    group by d.location_id
    

    但是,这可以使用条件聚合在一个查询中表示为

    select
    avg(case when d.location_id = 1700 then e.salary else 0 end) 
    AS "AVG SALARY for location 1700", 
    avg(case when d.location_id <> 1700 then e.salary else 0 end) 
    AS "AVG SALARY for locations other than 1700"
    from departments d
    join employees e on e.DEPARTMENT_ID = d.DEPARTMENT_ID
    

    【讨论】:

      【解决方案3】:

      您可以考虑使用case 而不是locationid

      select (case when d.lcoation_id = 1700 then 1700 else -1 end) as LocationId,
             round(avg(e.salary), 2) AS "AVG SALARY",
             count(d.LOCATION_ID)
      from departments d join
           employees e
           on e.DEPARTMENT_ID = d.DEPARTMENT_ID
      group by grouping sets((case when d.lcoation_id = 1700 then 1700 else -1 end));
      

      我不确定您是否需要grouping sets。如果你只想要两行,那么这可能就是你想要的:

      select (case when d.lcoation_id = 1700 then 1700 else -1 end) as LocationId,
             round(avg(e.salary), 2) AS "AVG SALARY",
             count(d.LOCATION_ID)
      from departments d join
           employees e
           on e.DEPARTMENT_ID = d.DEPARTMENT_ID
      group by (case when d.lcoation_id = 1700 then 1700 else -1 end);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-20
        • 1970-01-01
        • 1970-01-01
        • 2021-03-26
        • 2015-04-06
        相关资源
        最近更新 更多