在组的子组上应用COUNT函数

时间:2012-09-08 14:55:47

标签: sql oracle group-by analytic-functions

我编写了这个奇怪的例子,试图说明我想要做什么(这有点愚蠢,但请耐心等待):

考虑下表:

EMPLOYEES
Employees table data

已婚认证宗教只是布尔字段(对于Oracle,它们的类型为NUMBER(1,0)) 。

我需要提供针对每个雇佣年度的SQL,在以下薪资类别中显示已婚,认证和宗教雇员的数量:

  • A SALARY > 2000
  • B SALARY BETWEEN 1000 AND 2000
  • C SALARY < 1000

基于以上数据集,我希望得到以下内容:

Expected result

到目前为止,我只提出了以下SQL:

SELECT
COUNT(CASE WHEN married = 1 THEN 1 END) as MARRIED,
COUNT(CASE WHEN certified = 1 THEN 1 END) as certified,
COUNT(CASE WHEN religious = 1 THEN 1 END) as religious,
hire_year
FROM employees
GROUP BY hire_year;

执行此SQL的结果是:

Actual result

这几乎是我所需要的,但我还需要根据工资范围将这些计数器进一步划分为组。

我想一些分析函数,根据一些SQL表达式将组划分到存储桶中会有所帮助,但我无法弄清楚哪一个。我尝试使用 NTILE ,但它希望将正常数作为参数,而不是SQL表达式(例如SALARY BETWEEN X and Y)。

1 个答案:

答案 0 :(得分:7)

不,不需要分析功能;无论如何,它们很难在同一个查询中作为聚合函数。

您正在寻找case语句,您只需将其放入GROUP BY。

select hire_year
     , sum(married) as married
     , sum(certified) as certified
     , sum(religious) as religious
     , case when salary > 2000 then 'A'
            when salary >= 1000 then 'B'
            else 'C' end as salary_class
  from employees
 group by hire_year
     , case when salary > 2000 then 'A'
            when salary >= 1000 then 'B'
            else 'C' end

请注意,我已将您的count(case when...)更改为sum()。这是因为你使用的是布尔值1/0,所以这个方法会以相同的方式工作,但它更清晰。

出于同样的原因,我在工资计算中忽略了你的between;没有特别需要它,好像工资大于2000,第一个CASE已经完成。