2016-09-12 12 views
22

Mam poniższej tabeli pet w bazie menagerie:Dlaczego funkcja COUNT() pokazuje tylko jeden wiersz tabeli?

+--------+-------------+---------+------+------------+------------+ 
| name | owner  | species | sex | birth  | death  | 
+--------+-------------+---------+------+------------+------------+ 
| Tommy | Salman Khan | Lebre | NULL | 1999-01-13 | 0000-00-00 | 
| Bowser | Diane  | dog  | m | 1981-08-31 | 1995-07-29 | 
+--------+-------------+---------+------+------------+------------+ 

Teraz Jeżeli uruchomić następujące zapytanie:

select owner, curdate() from pet; 

pojawia się następujący komunikat:

+-------------+------------+ 
| owner  | curdate() | 
+-------------+------------+ 
| Salman Khan | 2016-09-12 | 
| Diane  | 2016-09-12 | 
+-------------+------------+ 

Wyjście pokaż wszystkie wartości owner i wartość zwróconą z curdate() w każdym wierszu.

Teraz gdybym uruchomić następujące zapytanie:

select owner, count(*) from pet; 

pojawia się następujący komunikat:

+-------------+----------+ 
| owner  | count(*) | 
+-------------+----------+ 
| Salman Khan |  2 | 
+-------------+----------+ 

Moje pytanie brzmi: jaka jest różnica między curdate() i count() funkcji, która sprawia MySQL do wyjścia z drugi ownerDiane w pierwszym przykładzie?

+0

@KevinEsche Tak, to jest wykonywane. Skopiowałem polecenia i tabele z 'cmd'. – user31782

+4

Otrzymujesz 1 linię, która została wkręcona bez 'group by': p – Drew

+10

To zapytanie jest nieprawidłowe i powinno wywołać błąd. (Być może nowsze wersje MySQL będą?) – jarlh

Odpowiedz

56

COUNT() to funkcja agregacji, która zwykle jest połączona z klauzulą ​​GROUP BY.

curdate() to funkcja daty, która wyprowadza bieżącą datę.

Tylko MySQL (o ile mi wiadomo) umożliwia tę składnię bez użycia klauzuli GROUP BY. Ponieważ go nie dostarczyłeś, COUNT(*) zlicza całkowitą liczbę wierszy w tabeli, a kolumna owner zostanie wybrana losowo/domyślnie optymalizator/według indeksów.

To powinno być zapytanie:

select owner, count(*) 
from pet 
group by owner; 

który mówi optymalizator liczyć sumę wierszy, dla każdy właściciel.

Gdy nie wspomniano o żadnej klauzuli grupowej - funkcje agregujące są stosowane do wszystkich danych tabeli.

Edycja: Liczenie które będą stosowane w każdym wierszu nie może być zwykle wykonane z COUNT() i zazwyczaj stosowane w funkcji analitycznej ->COUNT() OVER(PARTITION...) niestety nie istnieje w MySQL. Inną opcją jest utworzenie JOIN/CORRELATED QUERY dla tej dodatkowej kolumny.

Kolejna Edycja: Jeśli chcesz całkowitej liczby obok każdego właściciela, można użyć kwerendy sub:

SELECT owner, 
     (SELECT COUNT(*) FROM pet) as cnt 
FROM pet 
+1

Nie sądzę, aby grupa była konieczna, ponieważ SELECT COUNT (*) FROM pet; 'po prostu liczy wszystkie wiersze od zwierzaka. Tak więc, jak 'curdate()' wyświetla tę samą datę dwa razy w dwóch wierszach; 'count (*)' powinien także wyświetlać total_rows dwa razy w dwóch wierszach w moim drugim przykładzie. – user31782

+24

Tak, tylko MySQL, o ile mi wiadomo, ma te "cholerne torpedy", nie obchodzi mnie, czy to, o co prosiłeś, jest nonsensem, jeśli w ogóle mogę, zamierzam zgadywać i wracać zestaw wyników zamiast dawania użytkownikowi ostrzeżenia "postawy. –

+0

@ user31782 - różnica polega na tym, że w kolumnie "wybierz" masz dodatkową kolumnę. MySQL nie wie, czy zamierzasz grupować według tej kolumny, czy chciałeś arbitralnej wartości, czy też chciałeś zastosować do niej jakiś agregat. –

2

Większość systemów DBMS nie pozwoli na łączną funkcję jak count() z dodatkowym kolumny bez grupy przez; z powodu. DBMS nie wie, które kolumny grupować :-).

Rozwiązaniem jest grupą zapytanie przez kolumnę właściciela, tak:

SELECT owner, count(*) FROM pet GROUP BY owner; 
9

To wygląda dokładnie tak, jak w scenariuszu na dole tej strony: MySQL Documentation: 4.3.4.8 Counting Rows.

Jeśli ONLY_FULL_GROUP_BY nie jest włączony, zapytanie jest przetwarzany przez leczenia wszystkich wierszy jako jedna grupa, przy czym wartość wybrana dla każdego nazwie kolumny jest nieokreślony. Serwer jest wolny, aby wybrać wartość z dowolnego rzędu:

mysql> SET sql_mode = ''; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT owner, COUNT(*) FROM pet; 
+--------+----------+ 
| owner | COUNT(*) | 
+--------+----------+ 
| Harold |  8 | 
+--------+----------+ 
1 row in set (0.00 sec) 

Chyba w tym przypadku only_full_group_by nie jest ustawiony.

2

Liczba (*) funkcja agregująca zwraca tylko jedną wartość, tj. Całkowitą liczbę wierszy. I curdate() funkcja jest po prostu podać aktualną datę systemu.

4

Tylko MySQL pozwoli Ci na tego typu zapytania.

Powinieneś zawsze określać wszystkie kolumny, które nie są połączone z funkcją agregacji w klauzuli GROUP BY. Jeśli nie, dane zostaną połączone w jeden wiersz z poprawnie ustawionymi kolumnami zbiorczymi i wszystkimi innymi kolumnami wybranymi losowo lub z indeksami.

Więc trzeba to:

SELECT owner, count(*) FROM pet GROUP BY owner; 

co spowoduje:

Saknan Khan | 1 
Diane  | 1 

Czy to, co ma na celu osiągnięcie?

A może próbował to zrobić:

SELECT t.owner, 
     COUNT(*) as cnt 
FROM pet t 
CROSS JOIN pet s 
GROUP BY t.owner 

co spowoduje dodatkową kolumnę z całkowitej liczby obok każdego właściciela.

0

Tak, zazwyczaj dzieje się bez użycia klauzuli group by.

http://www.w3schools.com/sql/sql_groupby.asp Powinieneś przeczytać w linku wszystko o klauzuli group by.

wszystkie kolumny powinny być przywołane będzie agregacji lub grupę o

+0

Właściwie uczę się od [docs] (http://dev.mysql.com/doc/refman/5.7/en/counting-rows.html). Nie przeczytałem jednak na samym dole, zanim zadałem pytanie. – user31782

2

ostatnie zapytanie jest nieważny Oracle: ORA-00937: nie funkcji pojedynczej grupy. Oznacza to, że potrzebujesz klauzuli GROUP BY. Znalazłeś lukę w implementacji MySql. Nie należy polegać na takim zapytaniu w systemie produkcyjnym, w kolejnej wersji MySql może to nie działać.

Powiązane problemy