Mój profesor nauczył mnie, że „COUNT” nie liczy duplikatów

40

Na uniwersytecie mój profesor nauczył mnie w tym roku, że ta instrukcja SQL:

SELECT COUNT(length) FROM product

zwróci 2następujący zestaw danych:

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

Uzasadniła to stwierdzeniem, że COUNTnie liczy duplikatów.

Powiedziałem profesorowi, że myślałem, że popełniła błąd. Odpowiedziała mi, że niektóre DBMS mogą, ale nie muszą, liczyć duplikaty.

Po wypróbowaniu wielu DBMS, nigdy nie znalazłem takiego, który ma takie zachowanie.

Czy ten DBMS istnieje?

Czy jest jakiś powód, aby profesor uczył tego zachowania? I nawet nie wspominając, że inne DBMS mogą zachowywać się inaczej?


Do Twojej wiadomości, wsparcie kursu jest dostępne tutaj (w języku francuskim) . Dany slajd znajduje się w lewym dolnym rogu na stronie 10.

Jules Lamur
źródło
1
Ponieważ slajdy mówią o ANSi SQL, twój profesor się myli, nawet w standardzie z 1992 roku (patrz strona 125 tutaj contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ) wymienia różne zachowania do zliczania z lub bez DISTINCT. Możesz odwiedzić bibliotekę zaktualizowaną wersję (która zawiera więcej opcji takich jak ALL / OVER)
eckes

Odpowiedzi:

38

COUNT liczy duplikaty we wszystkich DBMS, o których wiem, ale.

Czy jest jakiś powód, aby profesor uczył tego zachowania

Tak, jest powód. W oryginalnej teorii relacyjnej (która leży u podstaw wszystkich współczesnych relacyjnych DBMS) relacja jest zbiorem w matematycznym znaczeniu tego słowa. Oznacza to, że żadna relacja nie może w ogóle zawierać duplikatów, w tym wszystkich relacji przejściowych, a nie tylko „tabel”.

Zgodnie z tą zasadą można powiedzieć, że SELECT length FROM productzawiera już tylko dwa wiersze, a zatem odpowiednie COUNTzwroty 2, a nie 3.


Na przykład w Rel DBMS, używając relacji podanej w pytaniu i składni Tutoriala D :

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

daje:

Wynik rel

Vadim Pushtaev
źródło
1
Ponieważ w tym roku odbyliśmy kursy teorii relacji z tym profesorem, myślę, że to poprawna odpowiedź. W każdym razie poproszę mojego profesora o więcej informacji.
Jules Lamur
2
Nauczyciel może mówił ogólnie o DBMS, nie tylko o SQL DBMS. Jak pokazuje edycja, istnieją implementacje modelu relacyjnego (np. Rel), w których COUNTzachowuje się inaczej niż implementacje SQL.
ypercubeᵀᴹ
47

Albo twój profesor popełnił błąd, albo źle zrozumiałeś, co powiedziała. W kontekście relacyjnych DBMS wdrożonych przez różnych dostawców funkcja agregująca COUNT(<expression>)zwraca liczbę wartości innych niż NULL <expression>w zestawie wyników (lub grupie).

Istnieje szczególny przypadek COUNT(*), który zwraca liczbę wierszy w zestawie wyników lub grupie, a nie liczbę wartości czegokolwiek. Jest to równoważne z COUNT(<constant expression>)np COUNT(1).

Wiele baz wsparcia COUNT(DISTINCT <expression>), które będzie powrócić liczbę unikalnych wartościach <expression>.

mustaccio
źródło
13

Jeśli twój profesor mówi o SQL, instrukcja jest błędna. COUNT(x)zwróci liczbę wierszy, w których x IS NOT NULLzawiera duplikaty. COUNT(*) or COUNT([constant])jest szczególnym przypadkiem, który policzy wiersze, nawet te, w których znajduje się każda kolumna NULL. Jednak duplikaty są zawsze liczone, chyba że określisz COUNT(distinct x). Przykład:

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 *) jest niepoprawny AFAIK.

Na marginesie, NULL wprowadza pewne nieintuicyjne zachowanie. Jako przykład:

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

to znaczy:

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

Jeśli mówi on o systemie relacyjnym opisanym na przykład w książce Bazy danych, typy i model relacyjny: Trzeci manifest autorstwa CJ Date i Hugh Darwen - byłoby to prawidłowe stwierdzenie.

Powiedz, że mamy relację:

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

koresponduje z:

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

to znaczy

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

co zwróci 2 .

Lennart
źródło
3

Tak to działa w MS SQL Server

COUNT (*) zwraca liczbę elementów w grupie. Obejmuje to wartości NULL i duplikaty.

COUNT (WSZYSTKIE wyrażenie) ocenia wyrażenie dla każdego wiersza w grupie i zwraca liczbę wartości niepustych.

COUNT (wyrażenie DISTINCT) ocenia wyrażenie dla każdego wiersza w grupie i zwraca liczbę unikatowych, niepustych wartości.

Daniel Björk
źródło
1

Jeśli stół wyglądałby tak,

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

można oczekiwać, że zapytanie zwróci 2, przynajmniej w Oracle DB, ponieważ wartości zerowe nie są liczone. Duplikaty są jednak liczone w porządku.

Terje
źródło
-7

może ona ma na myśli w połączeniu z unikalnym, Ale Count ma COUNT DUPLICATES. Są nauczyciele, którzy nie znają swoich rzeczy, nie martw się, po prostu poinformuj swoich kolegów z klasy / przyjaciół, aby kiedy przejdą na wyższy poziom dbania i prawdziwego życia, nie zapomną, lepiej jednak wyślij do nauczyciela anonimową wiadomość z pytaniem, że nie rozumiesz niektóre funkcje sql i chcesz demonstracji, poproś nauczyciela, aby zaproponował klasie, w jaki sposób wstawić duplikaty (nie mieć dużych danych), a kiedy używa liczby funkcji, masz ją. Niektóre osoby będą to odbierać, a także, gdy powie inne bazy danych, poproś ją, aby zapytała ją, które z nich, a następnie podwójnie ją złap i powiedz, że wypróbowałeś wszystkie te bazy danych, a one nie działają tak, jak powiedziała, a liczba ta podnosi duplikaty.

dasda
źródło
2
Nie jestem pewien, czy zamierzałbym celowo antagonizować nauczyciela. W przypadku niektórych osób może być całkowicie wystarczające spotkanie z nimi osobiście i zadawanie pytań, z gotowym kontrapunktem (tylko po to, aby pokazać, że masz powód, by o to pytać). Mimo to podstawy tego podejścia są aktualne; do PO konkretny kierunek do użycia.
RDFozz