2010-04-28 11 views
6

Jestem pewien, że ma to bardzo prostą odpowiedź, ale nie mogę tego znaleźć (nie jestem pewien, czego szukać!) . Standardowa liczba/grupę o zapytaniu może wyglądać następująco:MYSQL: COUNT z klauzulą ​​GROUP BY, LEFT JOIN i WHERE nie zwraca zerowych wartości

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 

i działa zgodnie z oczekiwaniami, wracając 0, jeśli nie zostaną znalezione żadne wiersze. Jednak:

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

działa tylko wtedy, gdy w tabeli 1 znajduje się co najmniej jeden wiersz i niewiarygodnie zwraca pusty zestaw wyników, jeśli występują zero wierszy. Naprawdę chciałbym, aby zwrócono 0! Ktoś mnie oświeca? Piwo może być dostarczone w zamian, jeśli jesteś w Londynie ;-)

Odpowiedz

4

Powodem, dla którego zwraca zero wierszy, jest zgrupowanie według wartości w tabeli_1. Ponieważ w tabeli_1 nie ma wartości, nie ma wierszy do zwrócenia. Powiedział inny sposób, jeśli zwrócony t1.any_col w zapytaniu z GROUP BY tak:

SELECT `t1`.`any_col`, COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

Co by wyświetlić na t1.any_col kiedy nie było żadnych wierszy? Jedynym sposobem na osiągnięcie tego, co chcesz, jest powiązanie wyników z inną kwerendą, która nie sprawdza żadnych wierszy w tabeli_1. W tym przykładzie używam widoku INFORMATION_SCHEMA po prostu do czegoś, o co mogę zapytać.

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 
UNION ALL 
SELECT 0 
FROM INFORMATION_SCHEMA.TABLES 
Where Not Exists(Select 1 From `table_1`) 
LIMIT 1 
+0

Dlaczego pierwszy przykład działa ładnie? Wszystko, czego brakuje, to klauzula WHERE, wciąż nie ma wierszy, a to zadziała dobrze ... –

+0

@Paul Norman - Pierwszy przykład działa, ponieważ wyraźnie widać wiersze w tabeli_1. Trzeci przykład nie działa, ponieważ najwyraźniej nie ma żadnych wierszy w tabeli_1, które mają wartość 123 dla "kolejnej_kolumny". Jeśli zapytanie bez grupy nie zwraca żadnych wierszy, to nie zwróci wierszy z grupowaniem. – Thomas

3

Oto lepsze rozwiązanie:

SELECT COUNT(*) FROM 
(SELECT `t2`.`name` 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col`) tmp 

Wystarczy owinąć SELECT COUNT(*) całego zapytania.

Problem polega na tym, że COUNT() zmienia się od znaczenia "podaj liczbę wierszy w zestawie wyników" do funkcji agregującej, co oznacza "podaj liczbę wierszy dla każdej grupy, które pasują do moich kryteriów", gdy są używane z GROUP BY zdanie. W twoim przypadku, ponieważ nie ma żadnych wierszy dla grupy, gdzie inna kolumna = 123, nic nie jest zwracane.

Jeśli zawiniesz to w innym SELECT COUNT(*), znowu mówisz: "podaj liczbę wierszy w zestawie wyników".

W pierwszym zapytaniu COUNT() współpracuje z GROUP BY. Ale bez określonych kryteriów otrzymujesz co najmniej jeden wiersz zwrócony z tabeli_1. Ponieważ nie ma odpowiadających rekordów table_2, wartość NULL wynosi 0 dla COUNT(). Nie używaj pierwszego zapytania. Choć zwraca to, czego oczekujesz, to tylko przypadek. Aby zapytanie było znaczące, należy podać kryteria dla t1.inna_kolumna w klauzuli WHERE.

Drugie zapytanie działa, ponieważ pytasz o liczbę wierszy zestawu wyników. Ponieważ nie ma wierszy, w których t1.inna_na kolumna = 123, zwracanych jest 0 wierszy, a COUNT() ma wartość 0.

+0

To tylko niestety mówi mi, ile jest wyjątkowych "grup". Więc jeśli istnieje tylko jedna wyraźna wartość 'any_col' w' table_1', ale 5 wierszy danych, gdzie 'any_col' = 5 to zwróci 1, a nie 5 w razie potrzeby (ponieważ zagnieżdżone SELECT zwróci tylko jeden wiersz). –

+0

@Paul, odśwież przeglądarkę. Naprawiłem to. Zauważ, że funkcja COUNT() jest używana tylko w zapytaniu zewnętrznym. –

+0

Sam wprowadziłem tę zmianę, ale wciąż myślę (a raczej testowałem), że GROUP BY w zapytaniu zagnieżdżonym oznacza, że ​​tylko jeden wiersz zostanie zwrócony, jeśli jedyne dane w tabeli mają pojedynczą wartość "any_col" (tj. jeśli każdy wiersz ma wartość 'any_col' = 5, to tylko jeden wiersz zostanie zwrócony przez zagnieżdżony wybór - jak można się spodziewać - a następnie oznacza, że ​​zliczanie tych danych daje tylko 1, a nie 5). Powyższe rozwiązanie działa jak zawsze, nigdy o tym nie myślisz! Dzięki za całą pomoc. Trudno jest być jasnym w tym małym pudełku! –