Подсчет отдельных и значение Null исключается совокупностью - PullRequest
6 голосов
/ 12 мая 2009

Я использую 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

Есть ли способ сделать подсчет отличным, не получая

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

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

  1. Отключение ANSI_WARNINGS
  2. Разделение на два запроса, один с различным числом и предложение where для исключения нулей, один с суммой:

    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, но мне не нравится дублирование кода.

Ответы [ 4 ]

6 голосов
/ 12 мая 2009
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 я разработал способ сделать это. Вы можете посчитать разные значения, включая нули, а затем удалить счет из-за нулей, если были какие-либо с использованием отличной суммы.

2 голосов
/ 25 октября 2011

Это поздняя заметка, но, поскольку это было возвращение в 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 (поскольку он учитывает записи, а не значения).

2 голосов
/ 12 мая 2009

Куда бы вы ни возвратили ноль, используйте

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
1 голос
/ 12 мая 2009

Если вам не нравится дублирование кода, то почему бы не использовать общее табличное выражение? например

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
...