Select Count(Distinct Value) возвращает 1

Я разрабатываю запрос в SSMS 2005, который выглядит примерно так:

SELECT COUNT(DISTINCT ColumnName) FROM Table WHERE ColumnName IS NOT NULL

Когда я запускаю запрос с COUNT(), он возвращает значение 1. Когда я запускаю его без COUNT(), SSMS сообщает правильное значение, например, 212 записей.

Рассматриваемый столбец имеет числовой тип данных (16, 0).

Для тех, кто может спросить, запрос полностью:

SELECT COUNT(DISTINCT O_ID) FROM vEmployers
INNER JOIN vEnrolment ON O_ID = E_EnrolmentEmployer
WHERE E_START >= '01-AUG-2008' AND E_START < '01-AUG-2009'
AND O_ID IS NOT NULL AND O_ID IN (
    SELECT O_ID FROM vEmployers
    INNER JOIN vEnrolment ON O_ID = E_EnrolmentEmployer
    WHERE E_Start < '01-AUG-2008' and E_Start >= '01-AUG-2007'
)

Этот запрос, по сути, дает данные о повторных продажах за два 12-месячных периода.

Итак, мне интересно, почему "COUNT(DISTINCT ColumnName)" возвращает 1, когда указано "ColumnName IS NOT NULL"?

Вот пример данных при запуске SELECT TOP 10 DISTINCT ColumnName FROM... etc:

1346116
1346131
1346425
1346923
1349935
1350115
1350153
2594787
2821944
2879631

person GateKiller    schedule 03.02.2010    source источник
comment
@GateKiller: вы абсолютно уверены, что просто опускаете COUNT и больше ничего?   -  person Quassnoi    schedule 03.02.2010
comment
Благодарю всю вашу помощь до сих пор, ребята :)   -  person GateKiller    schedule 03.02.2010
comment
Какая у вас версия SQL Server? К сожалению, только что увидел ссылку на 2005 год выше.   -  person Jeff Siver    schedule 05.02.2010


Ответы (4)


Использование числового (16, 0) заставило меня заподозрить, что это связано с типом данных. Добавьте CAST в предложение COUNT, чтобы привести его к типу INT:

Count(Distinct Cast(O_ID as Int))
person Turnkey    schedule 05.02.2010

Я предполагаю, что это потому, что все возвращаемые строки имеют одно и то же значение для O_ID. Вы можете сделать COUNT(*) или COUNT() для ключа, который уникален для каждой строки, чтобы получить количество строк.

person Håvard S    schedule 03.02.2010
comment
Все возвращенные строки уникальны благодаря предложению DISTINCT, что подтверждается выполнением запроса с COUNT(). - person GateKiller; 03.02.2010
comment
Можете привести короткую выдержку результатов без подсчета, просто показав несколько O_ID? - person Turnkey; 03.02.2010
comment
Что ж, COUNT(DISTINCT ...), конечно же, будет считать уникальные значения, отличные от NULL, и это все. Не делайте отличные, подсчитайте (*) или подсчитайте что-то уникальное во всех ваших строках БЕЗ предложения DISTINCT. - person Håvard S; 03.02.2010
comment
Вы правы в отношении того, как работает COUNT(DISTINCT...) и результат должен быть таким же, как подсчет строк без функции COUNT()... - person GateKiller; 03.02.2010
comment
Спасибо за подтверждение, просто добавлено в качестве ответа. - person Turnkey; 05.02.2010

Удалите DISTINCT, и вы получите счет для всех строк.

person Turnkey    schedule 03.02.2010
comment
Истинный. Но, как вы можете видеть из полного запроса, здесь задействовано объединение, так что это вернет повторяющиеся идентификаторы. И это не отвечает на вопрос, почему COUNT() возвращает 1, хотя не должен. - person GateKiller; 03.02.2010
comment
Да, это озадачивает, спасибо за публикацию дополнительной информации. Вы выполнили точно такой же запрос, чтобы получить выдержку, просто удалив счетчик? - person Turnkey; 03.02.2010
comment
Да, отрывок — это точно такой же запрос без использования функции COUNT(). Действительно, очень загадочно! - person GateKiller; 03.02.2010
comment
Интересно, может ли это быть связано с типом данных. Интересно, не могли бы вы добавить CAST в предложение COUNT, чтобы привести его к типу INT, чтобы посмотреть, изменит ли это что-нибудь? - person Turnkey; 03.02.2010
comment
Это полностью сработало Count(Distinct Cast(O_ID as Int)) :D. Пожалуйста, не могли бы вы представить это в качестве ответа, у меня есть несколько очков репутации для вас. - person GateKiller; 05.02.2010

Не могли бы вы выполнить эти запросы:

SELECT  COUNT(DISTINCT O_ID)
FROM    vEmployers
INNER JOIN
        vEnrolment
ON      O_ID = E_EnrolmentEmployer
WHERE   E_START >= '01-AUG-2008' AND
        E_START < '01-AUG-2009'
        AND O_ID IN
        (
        SELECT  O_ID
        FROM    vEmployers
        INNER JOIN
                vEnrolment
        ON      O_ID = E_EnrolmentEmployer
        WHERE   E_Start < '01-AUG-2008'
                AND E_Start >= '01-AUG-2007'
        )

а также

SELECT  DISTINCT TOP 5 O_ID
FROM    vEmployers
INNER JOIN
        vEnrolment
ON      O_ID = E_EnrolmentEmployer
WHERE   E_START >= '01-AUG-2008' AND
        E_START < '01-AUG-2009'
        AND O_ID IN
        (
        SELECT  O_ID
        FROM    vEmployers
        INNER JOIN
                vEnrolment
        ON      O_ID = E_EnrolmentEmployer
        WHERE   E_Start < '01-AUG-2008'
                AND E_Start >= '01-AUG-2007'
        )
ORDER BY
        O_ID

дословно, ничего не меняя?

person Quassnoi    schedule 03.02.2010
comment
Первый запрос возвращает одну строку со значением 1. Второй запрос возвращает пять строк уникальных значений. - person GateKiller; 03.02.2010
comment
@GateKiller: не могли бы вы опубликовать структуру таблиц? - person Quassnoi; 03.02.2010
comment
Какая информация вас интересует? Я не уверен, что мне будет разрешено опубликовать полную схему таблицы + каждая таблица имеет МНОГО столбцов. - person GateKiller; 03.02.2010
comment
@GateKiller: просто опубликуйте соответствующие столбцы: O_ID, E_START, E_EnrolmentEmployer: их типы данных, индексы, если они есть, и таблицы, которым они принадлежат. Также было бы неплохо увидеть планы выполнения для каждого запроса. Просто запустите SET SHOWPLAN_TEXT ON \n GO \n SELECT … (\n — новая строка) - person Quassnoi; 03.02.2010