Количество различных и нулевых значений исключается с помощью агрегата
-
21-08-2019 - |
Вопрос
Я использую SQL Server 2005.С помощью приведенного ниже запроса (упрощенного по сравнению с моим реальным запросом):
select a,count(distinct b),sum(a) from
(select 1 a,1 b union all
select 2,2 union all
select 2,null union all
select 3,3 union all
select 3,null union all
select 3,null) a
group by a
Есть ли какой-нибудь способ выполнить подсчет distinct без получения
"Предупреждение:Нулевое значение исключается с помощью агрегирования или другой операции набора ".
Вот альтернативы, которые я могу придумать:
- Выключение ANSI_WARNINGS
Разделение на два запроса, один с count distinct и предложением where для устранения нулей, один с sum:
select t1.a, t1.countdistinctb, t2.suma from ( select a,count(distinct b) countdistinctb from ( select 1 a,1 b union all select 2,2 union all select 2,null union all select 3,3 union all select 3,null union all select 3,null ) a where a.b is not null group by a ) t1 left join ( select a,sum(a) suma from ( select 1 a,1 b union all select 2,2 union all select 2,null union all select 3,3 union all select 3,null union all select 3,null ) a group by a ) t2 on t1.a=t2.a
Игнорируйте предупреждение в клиенте
Есть ли лучший способ сделать это?Вероятно, я пойду по маршруту 2, но мне не нравится дублирование кода.
Решение
select a,count(distinct isnull(b,-1))-sum(distinct case when b is null then 1 else 0 end),sum(a) from
(select 1 a,1 b union all
select 2,2 union all
select 2,null union all
select 3,3 union all
select 3,null union all
select 3,null) a
group by a
Благодаря Eoin я нашел способ сделать это.Вы можете посчитать различные значения, включая нули, а затем удалить счетчик из-за нулей, если таковые были, используя sum distinct.
Другие советы
Везде, где у вас возможно возвращено значение null, используйте
CASE WHEN Column IS NULL THEN -1 ELSE Column END AS Column
Это заменит все ваши нулевые значения на -1 на время выполнения запроса, и они будут подсчитаны / агрегированы как таковые, тогда вы можете просто сделать обратное в своем запросе с точной упаковкой...
SELECT
CASE WHEN t1.a = -1 THEN NULL ELSE t1.a END as a
, t1.countdistinctb
, t2.suma
Это запоздалое замечание, но, поскольку речь шла о возвращении Google, я хотел упомянуть об этом.
Изменение NULL на другое значение - плохая идея (tm).
COUNT() делает это, а не DISTINCT.
Вместо этого используйте DISTINCT в подзапросе, который возвращает число, и агрегируйте его во внешнем запросе.
Простым примером этого является:
WITH A(A) AS (SELECT NULL UNION ALL SELECT NULL UNION ALL SELECT 1)
SELECT COUNT(*) FROM (SELECT DISTINCT A FROM A) B;
Это позволяет COUNT(*)
будет использоваться, который не игнорирует значения NULL (поскольку он подсчитывает записи, а не значения).
Если вам не нравится дублирование кода, то почему бы не использовать общее табличное выражение?например ,
WITH x(a, b) AS
(
select 1 a,1 b union all
select 2,2 union all
select 2,null union all
select 3,3 union all
select 3,null union all
select 3,null
)
select t1.a, t1.countdistinctb, t2.suma from
(
select a,count(distinct b) countdistinctb from
x a
where a.b is not null
group by a
) t1
left join
(
select a,sum(a) suma from
x a
group by a
) t2 on t1.a=t2.a