SQL分组依据

时间:2010-11-17 12:49:39

标签: sql oracle group-by

使用ORACLE SQL。

我有一个表格“Employees”,其中一个属性为“hire_date”。我的任务(书籍练习)是写一个SELECT,它将告诉我在1995年,1996年,1997年和1998年雇用了多少员工。

类似的东西:

TOTAL     1995     1996     1997     1998
-----------------------------------------
20        4        5        29       2

单独计算每年的员工数量很容易,例如:

SELECT
  COUNT(*),
FROM
  employees e
WHERE
  e.hire_date like '%95'

但是当我必须以所需格式“聚合”数据时,我遇到了困难。 有什么建议吗?

6 个答案:

答案 0 :(得分:5)

我假设您的hire_date是varchar2,因为您在示例中执行了“like”子句。

每年一行的简单表会吗?

如果是这样,请在Oracle中尝试:

select case grouping(hire_date)
            when 0 then hire_date
            else 'TOTAL'
       end hire_date,
       count(hire_date) as count_hire_date
 from employees
 group by rollup(hire_date);

这应该是这样的:

hire_date  count_hire_date
1995       10
1996       20
1997       30
TOTAL      60

如果您确实需要将结果转换为您在问题中显示的内容,那么如果您知道运行查询之前的不同年份,则可以执行以下操作。例如,如果你知道你的表中只有1995,1996和1997,那么你可以用这个来转动结果:

SELECT
  MAX(CASE WHEN hire_date = 'TOTAL'    THEN ilv.count_hire_date   END) total,
  MAX(CASE WHEN hire_date = '1995'     THEN ilv.count_hire_date   END) count_1995,
  MAX(CASE WHEN hire_date = '1996'     THEN ilv.count_hire_date   END) count_1996,
  MAX(CASE WHEN hire_date = '1997'     THEN ilv.count_hire_date   END) count_1997
from (
    select case grouping(hire_date)
             when 0 then hire_date
             else 'TOTAL'
           end hire_date,
           count(hire_date) as count_hire_date
    from employees
    group by rollup(hire_date)
  ) ilv;

这有一个明显的缺点,你需要在每个可能的年份的主select语句中添加一个新子句。

答案 1 :(得分:4)

语法不直观。这利用了cut'n'paste编码:

SQL> select
  2      sum(case when to_char(hiredate, 'YYYY') = '1980' then 1 else 0 end) as "1980"
  3      , sum(case when to_char(hiredate, 'YYYY') = '1981' then 1 else 0 end) as "1981"
  4      , sum(case when to_char(hiredate, 'YYYY') = '1982' then 1 else 0 end) as "1982"
  5      , sum(case when to_char(hiredate, 'YYYY') = '1983' then 1 else 0 end) as "1983"
  6      , sum(case when to_char(hiredate, 'YYYY') = '1987' then 1 else 0 end) as "1987"
  7      , count(*) as total
  8  from emp
  9  /

      1980       1981       1982       1983       1987      TOTAL
---------- ---------- ---------- ---------- ---------- ----------
         1         10          1          0          2         20

Elapsed: 00:00:00.00
SQL>

答案 2 :(得分:1)

以下是我将如何在MS SQL中执行此操作 - 它在Oracle中类似,但我不想尝试为您提供Oracle代码,因为我通常不会编写它。这只是为了给你一个基本的骨架。

Select
  Year(e.hire_date),
  Count(1)
From
  employees e
Group By
  Year(e.hire_date)

答案 3 :(得分:1)

以下是我在MySQL中的做法,不知道这是否也适用于Oracle:

SELECT
 YEAR(hire_date), COUNT(*)
FROM 
 employees
GROUP BY 
 YEAR(hire_date)

答案 4 :(得分:1)

SELECT NVL(hire_date,'Total'), count(hire_date) 
   FROM Employees GROUP BY rollup(hire_date);

如果您需要PIVOT数据,请参阅A_M的答案。如果您有多年没有数据,但仍希望年份显示零计数,您可以执行以下操作:

SELECT NVL(a.Year,b.Year), NVL2(a.Year,a.Count,0) FROM
(
SELECT NVL(hire_date,'Total') Year, count(hire_date) Count
   FROM Employees GROUP BY rollup(hire_date)
) a
FULL JOIN
(
   SELECT to_char(2000 + rownum,'FM0000') Year FROM dual CONNECT BY rownum<=9
) b ON a.Year = b.Year;

这是一些测试数据。

create table Employees (hire_date Varchar2(4));

insert into Employees values ('2005');
insert into Employees values ('2004');
insert into Employees values ('2006');
insert into Employees values ('2009');
insert into Employees values ('2009');
insert into Employees values ('2005');
insert into Employees values ('2004');
insert into Employees values ('2006');
insert into Employees values ('2006');
insert into Employees values ('2006');

答案 5 :(得分:0)

我意识到这是6年前的事了,但我还发现了另一种使用Oracle中的DECODE功能的独特方式。

select
count(decode(to_char(hire_date, 'yyyy') , '2005', hire_date, null)) hired_in_2005,
count(decode(to_char(hire_date, 'yyyy') , '2006', hire_date, null)) hired_in_2006,
count(decode(to_char(hire_date, 'yyyy') , '2007', hire_date, null)) hired_in_2007,
count(*) total_emp
from employees 
where to_char(hire_date,'yyyy') IN ('2005','2006','2007')