Почему 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 *) просто вернет количество таких строк. Я что-нибудь упустил?
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 100COUNT(DISTINCT *)вернуть единственное значимое значение. Вот почему этот синтаксис не может работать.
В дополнение к тому, что сказали другие:
Следует помнить, что выполнение
count(distinct *)(если это было разрешено) на таблице, имеющей первичный ключ, будет идентичноselect count(*).Это происходит потому, что distinct * включает столбец PK, и поэтому каждая строка отличается от каждой другой строки.
И поскольку каждая нетривиальная таблица должна иметь первичный ключ (есть только очень несколько исключений из этого правила)
count(distinct *)можно "заменить" наcount(*)в любом случае.
Comments