SQL: как использовать функции DECODE и COUNT вместе - PullRequest
1 голос
/ 19 сентября 2019

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

"Следующие два вопроса очень сложны (для их выполнения необходимо использовать функцию DECODE).

Создайте запрос, который будет отображать общее количество сотрудников и общее количество сотрудников, принятых на работу в 1980, 1981, 1982 и 1987 годах. Укажите соответствующие заголовки столбцов.(5 баллов)

Total 1980  1981  1982  1987
----- ----- ----- ----- -----
   14     1    10     1     2

Вот функция, которую я набрал на сервере вместе с результатом.Я пробовал только 1980 год, поэтому я не теряю время, но мне также нужны 1981, 1982 и 1987 гг.*

выделено 14 строк.

Спасибо за помощь!

Ответы [ 2 ]

4 голосов
/ 19 сентября 2019

Предполагая, что столбец hiredate имеет тип данных DATE.

Позволяет сделать это без DECODE и использовать вместо него PIVOT:

Oracle Setup :

CREATE TABLE emp ( ename, hiredate ) AS
  SELECT 'A', DATE '1980-01-01' FROM DUAL UNION ALL
  SELECT 'B', DATE '1981-01-01' FROM DUAL UNION ALL
  SELECT 'C', DATE '1981-02-01' FROM DUAL UNION ALL
  SELECT 'D', DATE '1981-03-01' FROM DUAL UNION ALL
  SELECT 'E', DATE '1981-04-01' FROM DUAL UNION ALL
  SELECT 'F', DATE '1981-05-01' FROM DUAL UNION ALL
  SELECT 'G', DATE '1981-06-01' FROM DUAL UNION ALL
  SELECT 'H', DATE '1981-07-01' FROM DUAL UNION ALL
  SELECT 'I', DATE '1981-08-01' FROM DUAL UNION ALL
  SELECT 'J', DATE '1981-09-01' FROM DUAL UNION ALL
  SELECT 'K', DATE '1981-10-01' FROM DUAL UNION ALL
  SELECT 'L', DATE '1982-01-01' FROM DUAL UNION ALL
  SELECT 'M', DATE '1987-01-01' FROM DUAL UNION ALL
  SELECT 'N', DATE '1987-02-01' FROM DUAL;

Запрос :

SELECT *
FROM   (
  SELECT EXTRACT( YEAR FROM hiredate ) AS hireyear,
         COUNT(*) OVER () AS "Total"
  FROM   emp
)
PIVOT ( COUNT(*) FOR hireyear IN ( 1980, 1981, 1982, 1987 ) )

Вывод :

Total | 1980 | 1981 | 1982 | 1987
----: | ---: | ---: | ---: | ---:
   14 |    1 |   10 |    1 |    2

Запрос 2 :

Вы также можете сделать это с помощью CASE:

SELECT COUNT(*) AS "Total",
       COUNT(
         CASE
         WHEN hiredate >= DATE '1980-01-01' AND hiredate < DATE '1981-01-01'
         THEN hiredate
         END
       ) AS "1980",
       COUNT(
         CASE
         WHEN hiredate >= DATE '1981-01-01' AND hiredate < DATE '1982-01-01'
         THEN hiredate
         END
       ) AS "1981",
       COUNT(
         CASE
         WHEN hiredate >= DATE '1982-01-01' AND hiredate < DATE '1983-01-01'
         THEN hiredate
         END
       ) AS "1982",
       COUNT(
         CASE
         WHEN hiredate >= DATE '1987-01-01' AND hiredate < DATE '1988-01-01'
         THEN hiredate
         END
       ) AS "1987"
FROM   emp

Запрос 3 :

Или с помощью DECODE.

SELECT COUNT(*) AS "Total",
       COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1980, 'anything here' ) ) AS "1980",
       COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1981, 'anything here' ) ) AS "1981",
       COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1982, 'anything here' ) ) AS "1982",
       COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1987, 'anything here' ) ) AS "1987"
FROM   emp

Примечание: При подсчете вы считаете, что значение, переданное в COUNT, не равно * NULL, поэтому DECODEфункция может возвращать любое не NULL значение, когда оно совпадает, и оно будет подсчитано;и наоборот, до тех пор, пока значение, возвращаемое в COUNT, равно NULL, что является значением по умолчанию для DECODE, если вы не предоставите дополнительный четный аргумент, строка не будет считаться.

Так что вы можете использовать любое буквальное значение.Как строка:

COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1980, 'anything here' ) ) AS "1980"

или число

COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1980, 1 ) ) AS "1980"

или даже столбец hiredate (который, если у него 1980 год, то вы знаете, что это не NULL):

COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1980, hiredate ) ) AS "1980"

и если вы хотите явно указать возвращаемое значение из DECODE, если оно не совпадает, введите дополнительный аргумент NULL:

COUNT( DECODE( EXTRACT( YEAR FROM hiredate ), 1980, 42, NULL ) ) AS "1980"

дБ <> скрипка здесь

4 голосов
/ 19 сентября 2019

Ваш учитель хочет, чтобы вы делали условное агрегирование :

SELECT 
    COUNT(ename) AS "Total",
    SUM(DECODE(hire_date, 1980, 1, 0)) AS "1980",
    SUM(DECODE(hire_date, 1981, 1, 0)) AS "1981",
    SUM(DECODE(hire_date, 1982, 1, 0)) AS "1982",
    SUM(DECODE(hire_date, 1987, 1, 0)) AS "1987"
FROM emp;

Внутри каждого SUM, DECODE() проверяет hire_date относительно целевого значения и учитывает толькозаписи, имеющие соответствующую дату для каждого столбца.

Предполагается, что hire_date на самом деле год, что кажется нелогичным.Если это DATE, то вам нужно будет извлечь часть года, например, так:

SELECT 
    COUNT(ename) AS "Total",
    SUM(DECODE(EXTRACT(YEAR from hire_date), 1980, 1, 0)) AS "1980",
    SUM(DECODE(EXTRACT(YEAR from hire_date), 1981, 1, 0)) AS "1981",
    SUM(DECODE(EXTRACT(YEAR from hire_date), 1982, 1, 0)) AS "1982",
    SUM(DECODE(EXTRACT(YEAR from hire_date), 1987, 1, 0)) AS "1987"
FROM emp;

Обратите внимание, что DECODE() является специфичной для Oracle функцией, которая не поддерживается другими СУБД.Более стандартный способ написать это - использовать блоки CASE с такими выражениями, как:

    SUM(CASE WHEN EXTRACT(YEAR from hire_date) = 1980 THEN 1 ELSE 0 END) as "1980"
...