Мой профессор учил меня, что `COUNT` не считает дубликаты

40

В университете мой профессор научил меня в этом году, что это заявление SQL:

SELECT COUNT(length) FROM product

вернется 2со следующим набором данных:

|   product         |
|id | length | code |
|-------------------|
| 1 |    11  | X00  |
| 2 |    11  | C02  |
| 3 |    40  | A31  |

Она оправдала это тем, что COUNTне считает дубликатов.

Я сказал своему профессору, что, по-моему, она допустила ошибку. Она ответила мне, что некоторые СУБД могут или не могут считать дубликаты.

Попробовав много СУБД, я так и не нашел такую, которая бы имела такое поведение.

Существует ли эта СУБД?

Есть ли у профессора повод учить этому поведению? И даже не упоминая, что другие СУБД могут вести себя по-другому?


К вашему сведению, поддержка курса доступна здесь (на французском) . Соответствующий слайд находится в левом нижнем углу на странице 10.

Жюль Ламур
источник
1
Поскольку на слайдах говорится об ANSi SQL, ваш преподаватель ошибается, даже в стандарте 1992 года (см. Стр. 125 здесь contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ) перечислены различные варианты поведения для подсчета с DISTINCT и без него. Возможно, вы захотите посетить библиотеку с обновленной версией (которая включает в себя больше опций, таких как ВСЕ / НАД)
eckes

Ответы:

38

COUNT считает ли дубликаты во всех СУБД, о которых я знаю, но.

Есть ли у профессора повод учить этому поведению?

Да, есть причина. В оригинальной реляционной теории (которая лежит в основе всех современных реляционных СУБД) отношение является множеством в математическом смысле этого слова. Это означает, что ни одно отношение не может содержать дубликаты вообще, включая все переходные отношения, а не только ваши «таблицы».

Следуя этому принципу, вы можете сказать, что он SELECT length FROM productуже содержит только две строки, следовательно, соответствующих COUNTвозвращений 2нет 3.


Например, в СУБД Rel , используя отношение, данное в вопросе, и синтаксис Tutorial D :

SUMMARIZE product {length} BY {}: {c := COUNT()}

дает:

Rel результат

Вадим Пуштаев
источник
1
Поскольку в этом году у нас были курсы по реляционной теории с этим профессором, я думаю, что это правильный ответ. Во всяком случае, я попрошу своего профессора для получения дополнительной информации.
Жюль Ламур
2
Возможно, учитель говорил о СУБД в целом, а не только о СУБД SQL. Как показывает редактирование, существуют реализации реляционной модели (например, Rel), где COUNTповедение отличается от реализаций SQL.
ypercubeᵀᴹ
47

Либо ваш профессор ошибся, либо вы неправильно поняли, что она сказала. В контексте реляционных СУБД, реализованных различными поставщиками, агрегатная функция COUNT(<expression>)возвращает количество ненулевых значений <expression>в наборе результатов (или группе).

Существует особый случай COUNT(*), который возвращает количество строк в наборе результатов или группе, а не количество значений чего-либо. Это эквивалентно тому COUNT(<constant expression>), например , как COUNT(1).

Поддержка многих баз данных COUNT(DISTINCT <expression>), которая будет возвращать количество уникальных значений <expression>.

mustaccio
источник
13

Если ваш профессор говорит об SQL, утверждение неверно. COUNT(x)вернет количество строк, где х, IS NOT NULLвключая дубликаты. COUNT(*) or COUNT([constant])это особый случай, который будет считать строки, даже те, где каждый столбец NULL. Однако дубликаты всегда учитываются, если вы не укажете COUNT(distinct x). Пример:

with t(x,y) as ( values (null,null),(null,1),(1,null),(1,1) )

select count(*) from t
4

select count(1) from t
4

select count(distinct 1) from t
1

select count(x) from t
2

select count(distinct x) from t
1

COUNT(distinct *) является недействительным AFAIK.

В качестве примечания, NULL вводит неинтуитивное поведение. В качестве примера:

SELECT SUM(x) + SUM(y),  SUM(x + y) FROM T
4, 2

то есть:

SUM(x)+SUM(y) <> SUM(x+y)

Если он / она говорит о реляционной системе, как описано, например, в книге « Базы данных, типы и реляционная модель: третий манифест» С. Дж. Дейта и Хью Дарвена - это было бы правильным утверждением.

Скажи, что у нас есть отношение:

STUDENTS = Relation(["StudentId", "Name"]
                    , [{"StudentId":'S1', "Name":'Anne'},
                       {"StudentId":'S2', "Name":'Anne'},
                       {"StudentId":'S3', "Name":'Cindy'},
                     ])
SELECT COUNT(NAME) FROM STUDENTS

соответствует:

COUNT(STUDENTS.project(['Name']))

т.е.

COUNT( Relation(["Name"]
               , [{"Name":'Anne'},
                  {"Name":'Cindy'},
                ]) )

который бы вернулся 2 .

Леннарт
источник
3

Вот как это работает в MS SQL Server

COUNT (*) возвращает количество элементов в группе. Это включает в себя значения NULL и дубликаты.

COUNT (выражение ALL) вычисляет выражение для каждой строки в группе и возвращает количество ненулевых значений.

COUNT (выражение DISTINCT) вычисляет выражение для каждой строки в группе и возвращает количество уникальных ненулевых значений.

Даниэль Бьорк
источник
1

Если бы стол выглядел так,

|   product         |
|id | length | code |
|-------------------|
| 1 |    11  | X00  |
| 2 |    11  | C02  |
| 3 |  null  | A31  |

можно ожидать, что запрос вернет 2, по крайней мере, в Oracle DB, поскольку нули не учитываются. Дубликаты, однако, считаются просто отлично.

Терье
источник
-7

может быть, она имеет в виду в сочетании с уникальным, но граф делает удвоение счета. Есть некоторые учителя, которые не знают своего дела, не беспокоясь, просто сообщите своим одноклассникам / друзьям, чтобы, когда они перейдут на более высокий уровень и в реальной жизни они не забудут, лучше отправьте анонимное сообщение своему учителю, спрашивая ее, что они этого не сделали. поймите некоторые функции sql и хотите демонстрацию, попросите вашего учителя дать классу способ предложить, что вставлять, включая дубликаты (не иметь больших данных), и когда она использует счетчик функций, вы получаете ее. Некоторые люди подберут его. Также, когда она говорит другие базы данных, попросите вашего друга спросить ее, а затем дважды поймайте ее в ловушку и скажите, что вы перепробовали все эти базы данных, и они не работают, как она сказала, и этот счет обнаруживает дубликаты.

dasda
источник
2
Я не уверен, что хотел бы намеренно противодействовать учителю. С некоторыми из них может быть вполне достаточно просто встретиться с ними лично и спросить об этом, с вашим готовым контрпримером (просто чтобы показать, что у вас есть причина спрашивать). Тем не менее, основы подхода верны; до ОП конкретное направление для использования.
RDFozz