SQL Grouping By - PullRequest
       5

SQL Grouping By

1 голос
/ 17 ноября 2010

Использование 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 ]

5 голосов
/ 17 ноября 2010

Я предполагаю, что ваша 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;

Это имеет очевидный недостаток: вам нужно добавить новыйпредложение в основной оператор выбора для каждого возможного года.

4 голосов
/ 17 ноября 2010

Синтаксис не интуитивно понятен.Это использует кодирование пасты:

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>
1 голос
/ 17 ноября 2010
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');
1 голос
/ 17 ноября 2010

Вот как я это сделаю в MySQL, не знаю, относится ли это и к Oracle:

SELECT
 YEAR(hire_date), COUNT(*)
FROM 
 employees
GROUP BY 
 YEAR(hire_date)
1 голос
/ 17 ноября 2010

Вот как я бы это сделал в MS SQL - в Oracle это будет похоже, но я не хочу пытаться дать вам код Oracle, потому что я обычно его не пишу.Это просто чтобы получить базовый скелет.

Select
  Year(e.hire_date),
  Count(1)
From
  employees e
Group By
  Year(e.hire_date)
0 голосов
/ 09 ноября 2016

Я понимаю, что это 6 лет назад, но я также нашел другой уникальный способ сделать это, используя функцию DECODE в Oracle.

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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...