Proszę spojrzeć na tę tabelę:
mysql> desc s_p;
+-------------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| s_pid | int(10) unsigned | YES | MUL | NULL | |
| sm_id | int(10) unsigned | YES | MUL | NULL | |
| m_id | int(10) unsigned | YES | | NULL | |
| created | datetime | YES | | NULL | |
| s_date | datetime | YES | | NULL | |
| estimated_date | datetime | YES | MUL | NULL | |
+-------------------------+------------------+------+-----+---------+----------------+
Teraz spójrz na te zapytania:
mysql> select count(*) from s_p where estimated_date is null;
+----------+
| count(*) |
+----------+
| 190580 |
+----------+
1 row in set (0.05 sec)
mysql> select count(*) from s_p where estimated_date is not null;
+----------+
| count(*) |
+----------+
| 35640 |
+----------+
1 row in set (0.07 sec)
mysql> select count(*) from s_p;
+----------+
| count(*) |
+----------+
| 1524785 |
+----------+
Powyższe liczby nie są zgodne. Chociaż według mojego zrozumienia:
Liczyć za pomocą IS NULL
i Liczby z IS NOT NULL
powinny być równe, aby liczyć, gdy są pytane bez klauzuli where.
Masz pomysł na to, co się tutaj dzieje?
================================================== =
Aktualizacja 17 lutego 2012 r
Odkąd odkryłem, że wiele osób pyta o wartości, jakie ma obecnie szacowana data. Oto odpowiedź:
mysql> select distinct date(estimated_date) from s_p;
+----------------------+
| date(estimated_date) |
+----------------------+
| NULL |
| 2012-02-17 |
| 2012-02-20 |
| 2012-02-21 |
| 2012-02-22 |
| 2012-02-23 |
| 2012-02-24 |
| 2012-02-27 |
| 2012-02-28 |
+----------------------+
9 rows in set (0.42 sec)
Jak widać powyżej, szacunkowa data ma NULL lub prawidłowe wartości daty i godziny. Nie ma zer ani pustych ciągów „”.
Czy ten problem (oryginalny problem) może się zdarzyć, jeśli indeks w szacowanej dacie ma jakieś problemy?
================================================== =
Aktualizacja 18 lutego 2012 r
Oto dane wyjściowe tabeli tworzenia tabeli:
| s_p | CREATE TABLE `s_p` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`s_id` int(10) unsigned DEFAULT NULL,
`sm_id` int(10) unsigned DEFAULT NULL,
`m_id` int(10) unsigned DEFAULT NULL,
`created` datetime DEFAULT NULL,
`estimated_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `sm_id` (`sm_id`),
KEY `estimated_date_index` (`estimated_date`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=1602491 DEFAULT CHARSET=utf8 |
Znów mogę podejrzewać indeks tutaj tylko w przybliżoną datę.
Ponadto wersja serwera mysql to 5.5.12.
select count(*)
a nieselect count(estimated_date)
? Te dwa zwracają różne wyniki, ponieważ wartości NULL są ignorowane, jeśli to jedyna rzecz, którą się liczy.SELECT COUNT(*),SUM(CASE WHEN estimated_date IS NULL THEN 1 ELSE 0 END),SUM(CASE WHEN estimated_date IS NOT NULL THEN 1 ELSE 0 END) from s_p
- który powinien uzyskać wszystkie liczby za jednym razem.CHECK TABLE
na nim uruchomić ? Biorąc pod uwagę dziko większą liczbę pełny wiersz, bym odgadnąćDELETE
oszalał gdzieś.Odpowiedzi:
Czy masz jakieś zero dat? Wartości Datetime
0000-00-00 00:00:00
są uważane przez MySQL za jednocześnie spełniająceis null
iis not null
:Zobacz: http://bugs.mysql.com/bug.php?id=940
Jest to klasyfikowane jako „nie błąd”. Sugerują obejście: użyj trybu ścisłego, który przekształci ostrzeżenie wstawiania na błąd.
Powiedziawszy to wszystko, samo to nie może wyjaśnić dzikiej zmienności wyników, które otrzymujesz (suma
is null
iis not null
liczby powinny przekraczać nieograniczoną liczbę) ...źródło
DATE
lubDATETIME
jest zdefiniowane jakoNOT NULL
. W pytaniu tutaj kolumna jest zdefiniowana jako nullable. Ten błąd jest jednak kolejnym powodem, aby uruchomić MySQL tylko w trybie ścisłym.@ypercube:
Niedawno zapytano mnie, czy myślę, że błąd regresji „WYBIERZ LICZBĘ (DISTINCT) powoduje awarię InnoDB, gdy operand jest w kluczu podstawowym lub indeksie unikatowym” może być przyczyną tego.
Oto moja odpowiedź (pierwotnie tutaj):
http://www.chriscalender.com/?p=315&cpage=1#comment-1460
Nie sądzę, że to ten sam błąd. Ten błąd dotyczy bardziej awarii i wymaga w szczególności SELECT COUNT (DISTINCT), a także operand WHERE znajduje się w kluczu podstawowym lub indeksie Unique.
Twój błąd / problem nie ma DISTINCT, nie ulega awarii, a indeks w kolumnie daty i godziny nie jest kluczem podstawowym ani unikalnym. Jednak jest to trochę dziwne poza mankietem, więc trochę przeszukałem i natknąłem się na ten błąd, który wydaje się być bardziej zaangażowany / związany:
http://bugs.mysql.com/bug.php?id=60105
W rzeczywistości jest oznaczony jako „nie jest to błąd”, ale pokazuje / opisuje, w jaki sposób możesz popaść w dziwne zachowanie, kiedy masz daty / godziny danych z „0000-00-00” i używając IS NULL i IS NOT NULL.
Zastanawiam się, czy masz któryś z tych wierszy „0000-00-00”, który może mieć wpływ na liczbę?
Zwróć uwagę na autora, który komentuje w raporcie o błędzie, również wspomina o tej stronie:
Jeśli tak nie jest, zdecydowanie polecam aktualizację i wypróbowanie tego w najnowszej wersji 5.5, czyli w wersji 5.5.21 (stan na 22.02.2012), ponieważ minęło 9 miesięcy (i 9 wydań) od 5.5.12 został wydany.
Pamiętaj, że powinieneś być w stanie zrzucić tabelę (i dane) i zaimportować ją do innej instancji testowej, aby ją przetestować. W ten sposób nie wpływasz na maszynę produkcyjną i możesz skonfigurować instancję testową w kilka minut.
Następnie, jeśli to nie robi różnicy, będziesz w stanie przetestować inne elementy, na przykład przekonwertować tabelę na MyISAM, aby sprawdzić, czy problem jest globalny, czy tylko specyficzny dla InnoDB.
Zauważyłem też, że indeks „data_szacowania” to:
KLUCZ
estimated_date_index
(estimated_date
) ZA POMOCĄ BTREEZwróć uwagę na „UŻYWANIE BTREE”. Być może spróbuj tego bez USING BTREE i sprawdź, czy nadal widzisz to samo zachowanie. (Lub usuń indeks całkowicie tylko po to, aby przetestować .. to wszystko pomoże zawęzić problem).
Mam nadzieję że to pomoże.
źródło
Wypróbuj zapytanie
źródło
W układzie stołu widzę coś interesującego, co woła: „Nie mam ochoty liczyć”. Mam zamiar powiedzieć tylko przeczucie.
Uruchomiłeś już to zapytanie
Uruchom jako COUNT / GROUP BY
Otrzymasz ostateczne liczby, których szukałeś.
Dlaczego jednak liczby dla wartości NULL i NOT NULL są obliczane poprawnie? Ponownie jest to tylko wykształcone przypuszczenie.
Masz
estimated_date
indeksowaną kolumnę . Oto, co chcę, abyś spróbował:To nie jest literówka. Chcę, żebyś biegł
SHOW INDEX FROM s_p;
cztery (4) razy. Spójrz naCardinality
kolumnę. Ponieważ tabelas_p
w InnoDB oczekuje, że kolumna Kardynalność będzie za każdym razem inna. Dlaczego?InnoDB uzyskuje wartość Kardynalności poprzez jej oszacowanie (NIE PRZEZNACZENIE PUNKTU) poprzez zliczanie za pomocą wpisów strony BTREE. Sprawdź swoją zmienną systemową innodb_stats_on_metadata . Powinien być włączony. Jeśli jest już włączony, wyłącz go i ponownie uruchom oryginalne zapytania, aby sprawdzić, czy coś się poprawi. ZRÓB TO TYLKO JAKO OSTATNI OŚRODEK !!!
Zamiast tych zapytań:
Próbować
Powinno to dać ci liczbę wierszy z niepustą datą szacunkową.
Inne podejście, które możesz chcieć eksperymentować z tym zapytaniem dotyczącym siły brutalnej przy użyciu funkcji ISNULL :
Mam nadzieję, że te sugestie pomogą !!!
źródło
Jest to oczekiwane. W przypadku kolumny, która ma wartość zerową, 0 == NULL = "" i tak dalej. Tak więc pierwsze sprawdzenie faktycznie zwraca wiersze, w których nie ustawiono daty lub jej postrzeganie jest analogiczne do „0 / NULL”
źródło
0
nigdy nie jest równyNULL
. Pusty ciąg (''
) nie jest taki sam jakNULL
oba, chyba że pracujesz z Oracle.