Подсчет значений null как уникального значения
мне нужно подсчитать различные значения в столбце, такие как:
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 значение и использовать distinct, чтобы избежать повторного подсчета значений?
Я изучаю расширенный SQL, они хотят, чтобы я эти требования для всех решений:
попробуйте минимизировать количество подзапросов, необходимых для решения запроса. Кроме того, вам не разрешается использовать следующие конструкции:
- выберите из или выберите. Вам разрешено иметь подзапросы (выберите в WHERE или HAVING)
- комбинации агрегационных функций, таких как COUNT (COUNT. ..)), SUM (COUNT. ..)) и тому подобное.
- союз, если вы можете избежать этого.
- нестандартные функции (такие как NVL)
- случае
12 ответов
Если час-это число, то если это может быть только целое число:
select count(distinct coalesce(hour, 0.1)) cnt from test;
в противном случае, если это может быть любая плавающая точка, измените NULL на строку char.
например
select count(distinct coalesce(to_char(hour), 'a')) cnt from test;
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 ;
я бы сказал, что ваши требования довольно странные, учитывая, что вы почти наверняка получите более эффективный запрос, просто используя NVL()
, COALESCE()
или CASE
. Тем не менее, мне удалось получить правильный результат (и справиться с наличием или отсутствием NULL
values), используя только подзапросы. Мне не удалось сделать это без использования подзапроса в FROM
пункт еще.
запрос 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
для преобразования ненулевых значений в тип данных VARCHAR2 иNVL
преобразованиеNULL
значения для VARCHAR2'NULL'
или - просто использовать
NVL
с магическим числом, что вы знаете, что никогда не будете присутствовать в результирующем наборе (т. е. из-за ограничений на таблице).
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 |
ответ Андрес-это тот, который отвечает требованиям отлично и без использования какой-либо функции вообще, кроме COUNT
:
select count(distinct hour||' ') from hours;
ближе всего я мог бы получить соответствие указанным критериям, это: (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, поэтому, вероятно, это противоречит духу вопроса, но это соответствует критерии в списке по крайней мере.
вероятно, самый простой способ-использовать DUMP
:
SELECT COUNT(DISTINCT DUMP(hour)) AS distinct_count
FROM hours;
выход: 3
Ах.. домашнее задание. Разве все не так просто?
SELECT COUNT(hour)
FROM hours
нули не учитываются.
понял! Мой плохой для не чтения требований должным образом.
SELECT COUNT(DISTINCT COALESCE(hour,-1))
FROM hours