oracle SQL 分组依据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4204492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 21:58:36  来源:igfitidea点击:

SQL Grouping By

sqloraclegroup-by

提问by Andrei Ciobanu

Using ORACLE SQL.

使用 ORACLE SQL。

I have a table 'Employees' with one of the attributes 'hire_date' . My task (book exercise) is to write a SELECTthat will show me how many employees were hired in 1995, 1996, 1997 and 1998 .

我有一个表 ' Employees',其中一个属性是 ' hire_date'。我的任务(书本练习)是写一份报告SELECT,显示 1995 年、1996 年、1997 年和 1998 年雇佣了多少员工。

Something like:

就像是:

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

Individually is easy to count the number of employees for every year, eg:

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

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

But I am having difficulties when I have to 'aggregate' the data in the needed format . Any suggestions ?

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

回答by A_M

I'm assuming your hire_date is a varchar2, since you are doing a "like" clause in your example.

我假设你的hiring_date 是一个varchar2,因为你在你的例子中做了一个“like”子句。

Will a simple table with one row per year do?

一张每年只有一行的简单表格可以吗?

If so, try this in Oracle:

如果是这样,请在 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);

That should give something like:

那应该给出类似的东西:

hire_date  count_hire_date
1995       10
1996       20
1997       30
TOTAL      60

If you do need to pivot your results into something like you've shown in your question, then you can do the following if you know the distinct set of years prior to running the query. So for example, if you knew that you only had 1995, 1996 and 1997 in your table, then you could pivot the results using this:

如果您确实需要将结果转换为您在问题中显示的内容,那么如果您在运行查询之前知道不同的年份集合,则可以执行以下操作。因此,例如,如果您知道您的表中只有 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;

This has the obvious disadvantage of you needing to add a new clause into the main select statement for each possible year.

这有一个明显的缺点,即您需要为每个可能的年份在主选择语句中添加一个新子句。

回答by APC

The syntax is not intuitive. This leverages cut'n'paste coding:

语法不直观。这利用了剪切粘贴编码:

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>

回答by Leigh Riffel

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

If you need to PIVOT the data see A_M's answer. If you have years for which you have no data, yet still want the year to show up with a zero count you could do something like the following:

如果您需要 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;

Here is some test data.

下面是一些测试数据。

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');

回答by Brandon Montgomery

Here's how I would do it in MS SQL - it will be similar in Oracle, but I don't want to try to give you Oracle code because I don't usually write it. This is just to get you a basic skeleton.

下面是我在 MS SQL 中的做法——它在 Oracle 中是类似的,但我不想尝试给你 Oracle 代码,因为我通常不编写它。这只是为了给你一个基本的骨架。

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

回答by Brandon Montgomery

Here's how I'd do it in MySQL, don't know if this applies to Oracle too:

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

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

回答by Aklopper

I realize this is 6 years ago, but I also found another unique way of doing this using the DECODE function in Oracle.

我意识到这是 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')