Почему COUNT (DISTINCT ( * )) не работает?



Я до сих пор удивляюсь, почему такой простой запрос не работает:



SELECT COUNT(DISTINCT *) FROM dbo.t_test     


Где как



SELECT COUNT(DISTINCT col1) FROM dbo.t_test


И



SELECT DISTINCT * FROM dbo.t_test 


Работает.



Какова альтернатива?



Правка:



DISTINCT * проверяет уникальность комбинированного ключа (col1, col2,...) и возвращает эти строки. Я ожидал, что COUNT (DISTINCT *) просто вернет количество таких строк. Я что-нибудь упустил?

548   4  

4 ответов:

Истина в том, что SQL (сервер) или любая другая реализация SQL не должна делать все под солнцем.

Есть причины ограничить синтаксис SQL определенными элементами, от уровня синтаксического анализа до оптимизации запросов, предсказуемости результатов и просто здравого смысла.

Агрегатная функция COUNT обычно реализуется как потоковая агрегатная функция с затвором для одного элемента, будь то * (Record count, просто используйте статический токен) или colname (маркер инкремента только тогда, когда он не равен нулю) или distinct colname (хэш/ведро с одним ключом).

Когда вы просите COUNT(DISTINCT *) или, если на то пошло, COUNT(DISTINCT a,b,c) - Да, это, безусловно, может быть сделано для вас, если некоторые СУБД сочтут нужным реализовать его однажды; но это (1) достаточно необычно (2) добавляет работу к синтаксическому анализатору (3) добавляет сложность реализации COUNT.

У Марка естьправильная альтернатива .

Это не работает, потому что вы можете указать только одно выражение в COUNT(DISTINCT ...) согласно документации :

COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )
Если вы посмотрите внимательно, то увидите, что разрешенная грамматика не включает COUNT(DISTINCT *).

Альтернатива такова:

SELECT COUNT(*) FROM
(
    SELECT DISTINCT * FROM dbo.t_test 
) T1

В качестве простого примера предположим, что у вас есть два столбца, A и B.

A    B
1    100
2    100
3    100
Существует три различных значения А, но только одно определенное значение В. Было бы невозможно для COUNT(DISTINCT *) вернуть единственное значимое значение. Вот почему этот синтаксис не может работать.

В дополнение к тому, что сказали другие:

Следует помнить, что выполнение count(distinct *) (если это было разрешено) на таблице, имеющей первичный ключ, будет идентично select count(*).

Это происходит потому, что distinct * включает столбец PK, и поэтому каждая строка отличается от каждой другой строки.

И поскольку каждая нетривиальная таблица должна иметь первичный ключ (есть только очень несколько исключений из этого правила) count(distinct *) можно "заменить" на count(*) в любом случае.

Comments

    Ничего не найдено.