Подсчет нулевых значений как уникального значения

Мне нужно посчитать разные значения в столбце, такие как:

Hours
1
1
2
null
null
null

Результат должен быть: 3. Мой запрос:

select count(distinct hour) from hours;

но он возвращает: 2. Я также проверил:

select count(*) from hours group by hour

но он возвращает три строки:

(1) 3
(2) 2
(3) 1

Как я могу считать нулевые значения как 1 значение и использовать отличные, чтобы избежать подсчета повторных значений?

Я изучаю продвинутый SQL, мне нужны эти требования для всех решений:

Постарайтесь минимизировать количество подзапросов, необходимых для решения запроса. Кроме того, вам не разрешено использовать следующие конструкции:

  • ВЫБРАТЬ В ОТ или ВЫБРАТЬ. Вам разрешено иметь подзапросы (ВЫБЕРИТЕ в ГДЕ или В НАЛИЧИИ)
  • Комбинации функций агрегирования, такие как COUNT (COUNT...)), SUM (COUNT...)) и тому подобное.
  • СОЮЗ, если вы можете избежать этого.
  • Нестандартные функции (такие как NVL)
  • ДЕЛО

Ответ 1

select  count(distinct col1) + count(distinct case when col1 is null then 1 end)
from    YourTable

Ответ 2

если hour - это число, то если это может быть только целое число:

select count(distinct coalesce(hour, 0.1)) cnt from test;

иначе, если это может быть любая плавающая точка, измените значение NULL на строку char.

например,

select count(distinct coalesce(to_char(hour), 'a')) cnt from test;

Ответ 3

select 
   count(0) 
from
  (
      select distinct hour from hours
  )

SqlFiddle

Ответ 4

SELECT
      ( SELECT COUNT(DISTINCT hour)
        FROM hours
      )
    + CASE WHEN EXISTS
           ( SELECT *
             FROM hours
             WHERE hour IS NULL
           )
        THEN 1 
        ELSE 0
      END
   AS result
FROM dual ;

Ответ 5

возможно

    select count(distinct hour||' ') from hours;

будет делать?

Ответ 6

select count(distinct nvl(hour,0)) from hours;

Ответ 7

Я бы сказал, что ваши требования довольно странные, учитывая, что вы почти наверняка получите более эффективный запрос, просто используя NVL(), COALESCE() или CASE. Однако мне удалось получить правильный результат (и справиться с наличием или отсутствием значений NULL), используя только подзапросы. Мне не удалось сделать это, не используя подзапрос в предложении FROM.

SQL Fiddle

Запрос 1:

SELECT nnh.not_null_hours + nh.null_hours
FROM (
  SELECT COUNT(DISTINCT t.hour) not_null_hours
  FROM example_table t
) nnh
CROSS JOIN (
  SELECT 1 null_hours
  FROM dual
  WHERE EXISTS (
    SELECT 1
    FROM example_table t
    WHERE t.hour IS NULL
  )
  UNION ALL
  SELECT 0 null_hours
  FROM dual
  WHERE NOT EXISTS (
    SELECT 1
    FROM example_table t
    WHERE t.hour IS NULL
  )
) nh

Результаты:

| NNH.NOT_NULL_HOURS+NH.NULL_HOURS |
------------------------------------
|                                3 |

Это потребует больших усилий, чтобы справиться с требованиями. Гораздо проще использовать NVL, а затем один из двух простых вариантов:

  • Используйте TO_CHAR для преобразования значений, отличных от NULL, к типу данных VARCHAR2 и NVL для преобразования значений NULL в VARCHAR2 'NULL' или
  • Просто используйте NVL с магическим номером, который, как вы знаете, никогда не будет присутствовать в наборе результатов (т.е. из-за ограничений в таблице).

Запрос 1:

SELECT 
  COUNT(DISTINCT NVL(TO_CHAR(hour), 'NULL')) using_to_char_null
, COUNT(DISTINCT NVL(hour, -1)) using_magic_number
FROM example_table

Результаты:

| USING_TO_CHAR_NULL | USING_MAGIC_NUMBER |
-------------------------------------------
|                  3 |                  3 |

Ответ 8

Ответа на этот вопрос Andres: это тот, который отвечает требованиям совершенно и без какой-либо функции, кроме COUNT:

select count(distinct hour||' ') from hours;

Я искал то же самое для другой цели (я мог бы использовать что-либо вообще), но это не показалось мне правильным или эффективным, пока я не увидел это, спасибо Andres, такое простое решение, но мощное.

Ответ 9

Ближе всего я могу подобрать критерии, указанные ниже: (SQL Fiddle)

Запрос 1:

SELECT COUNT(*)
FROM example_table t1
WHERE t1.ROWID IN (
  SELECT MAX(t2.ROWID)
  FROM example_table t2
  GROUP BY t2.hour
)

Результаты:

| COUNT(*) |
------------
|        3 |

Не уверен, что псевдоколонка ROWID разрешена, учитывая другие ограничения, но она работает и изящно обрабатывает значения NULL. Я не думаю, что ROWID существует вне Oracle, поэтому, вероятно, это противоречит духу вопроса, но оно соответствует указанным критериям.

Ответ 10

Вероятно, самый простой способ - использовать DUMP:

SELECT COUNT(DISTINCT DUMP(hour)) AS distinct_count
FROM hours;

Выход: 3

DBFiddle Demo

Ответ 11

Джампаоло побеждает

msgstr "выбрать количество (отличный nvl (час, 0)) от часов;"

может ты сможешь попробовать это

выберите 3 из часа;

Ответ 12

А.. домашнее задание. Разве это не так просто?

SELECT COUNT(hour) 
  FROM hours

NULLS не подсчитываются.

Получил! Мой плохой для того, чтобы не правильно читать требования.

SELECT COUNT(DISTINCT COALESCE(hour,-1)) 
  FROM hours

Ответ 13

Select count(1)-count(hour) from hours;

Это даст вам вывод 3