Количество различных и нулевых значений исключается с помощью агрегата

StackOverflow https://stackoverflow.com/questions/851642

Вопрос

Я использую 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 без получения

"Предупреждение:Нулевое значение исключается с помощью агрегирования или другой операции набора ".

Вот альтернативы, которые я могу придумать:

  1. Выключение ANSI_WARNINGS
  2. Разделение на два запроса, один с 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
    
  3. Игнорируйте предупреждение в клиенте

Есть ли лучший способ сделать это?Вероятно, я пойду по маршруту 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top