Bitte schauen Sie sich diese Tabelle an:
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 | |
+-------------------------+------------------+------+-----+---------+----------------+
Schauen Sie sich jetzt diese Fragen an:
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 |
+----------+
Die obigen Zählungen stimmen nicht überein. Während nach meinem Verständnis:
Count with IS NULL
und Count with IS NOT NULL
sollten gleich count sein, wenn sie ohne where-Klausel abgefragt werden.
Irgendeine Idee, was hier passiert?
=============================================== =
Update am 17. Februar 2012
Seitdem habe ich festgestellt, dass viele Leute nach den Werten fragen, die estimated_date derzeit hat. Hier ist die Antwort:
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)
Wie Sie oben sehen können, hat estimated_date entweder NULL oder einen gültigen datetime-Wert. Es gibt keine Nullen oder leere Zeichenfolgen "".
Kann dies (ursprüngliches Problem) passieren, wenn der Index für Estimated_Date ein oder mehrere Probleme aufweist?
=============================================== =
Update am 18. Februar 2012
Hier ist die Ausgabe von show create table:
| 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 |
Wiederum kann ich hier nur einen Index für Estimated_date vermuten.
Die Version des MySQL-Servers ist 5.5.12.
select count(*)
und nicht tunselect count(estimated_date)
? Diese beiden Werte geben unterschiedliche Ergebnisse zurück, da NULL-Werte ignoriert werden, wenn dies das einzige ist, was Sie zählen.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
- die alle der Zählungen in einem Rutsch bekommen sollte.CHECK TABLE
? In Anbetracht der wild wachsenden Anzahl an Zeilen würde ich vermuten, dassDELETE
irgendwo etwas verrückt geworden ist.Antworten:
Hast du ein Datum von null? Datetime-Werte von
0000-00-00 00:00:00
werden von MySQL als gleichzeitig befriedigendis null
undis not null
:Siehe: http://bugs.mysql.com/bug.php?id=940
Dies wird als "kein Fehler" eingestuft. Sie schlagen eine Problemumgehung vor: Verwenden Sie den strikten Modus, der die Einfügewarnung in einen Fehler umwandelt.
Abgesehen davon kann dies allein nicht die wilde Variation der Ergebnisse erklären, die Sie erhalten (die Summe der
is null
undis not null
-Zahlen sollte die uneingeschränkte Anzahl überschreiten) ...quelle
DATE
oderDATETIME
als definiert istNOT NULL
. In der hier gestellten Frage ist die Spalte als nullwertfähig definiert. Dieser Fehler ist jedoch ein weiterer Grund, MySQL nur im strikten Modus auszuführen.@ypercube:
Kürzlich wurde ich gefragt, ob der Regressionsfehler "SELECT COUNT (DISTINCT) stürzt in InnoDB ab, wenn sich der Operand WHERE im Primärschlüssel oder im eindeutigen Index befindet" die Ursache dafür sein könnte.
Hier ist meine Antwort (ursprünglich hier):
http://www.chriscalender.com/?p=315&cpage=1#comment-1460
Ich denke nicht, dass dies der gleiche Fehler ist. Dieser Fehler befasst sich eher mit dem Absturz und erfordert speziell SELECT COUNT (DISTINCT) sowie den Operanden WHERE im Primärschlüssel oder im eindeutigen Index.
Ihr Fehler / Problem hat nicht das DISTINCT, es stürzt nicht ab und der Index für die datetime-Spalte ist weder ein Primärschlüssel noch eindeutig. Allerdings ist es etwas seltsam, also habe ich ein bisschen gesucht und bin auf diesen Fehler gestoßen, der wahrscheinlich eher damit zu tun hat:
http://bugs.mysql.com/bug.php?id=60105
Eigentlich wird es als "kein Fehler" bezeichnet, aber es zeigt / beschreibt, wie Sie auf seltsames Verhalten stoßen können, wenn Sie Daten mit "0000-00-00" haben und IS NULL und IS NOT NULL verwenden.
Ich frage mich, ob Sie eine dieser '0000-00-00'-Zeilen haben, die sich auf die Anzahl auswirken könnten.
Beachten Sie, dass der Entwickler, der Kommentare im Fehlerbericht abgibt, auch diese Seite erwähnt:
Wenn dies nicht der Fall ist, würde ich auf jeden Fall empfehlen, ein Upgrade und einen Versuch mit 5.5 durchzuführen. Dies ist 5.5.21 (Stand 22.02.2012), da seit 5.5.12 9 Monate (und 9 Releases) vergangen sind wurde veröffentlicht.
Beachten Sie, dass Sie die Tabelle (und die Daten) sichern und in eine andere Testinstanz importieren können sollten, nur um sie zu testen. Auf diese Weise haben Sie keine Auswirkungen auf eine Produktionsmaschine, und Sie können eine Testinstanz in wenigen Minuten einrichten.
Sollte dies dennoch keinen Unterschied machen, können Sie einige andere Elemente testen, z. B. die Tabelle in MyISAM konvertieren, um festzustellen, ob das Problem global oder nur für InnoDB spezifisch ist.
Oder mir ist aufgefallen, dass der Index für 'estimated_date' wie folgt lautet:
KEY
estimated_date_index
(estimated_date
) unter Verwendung von BTREEBeachten Sie den "USING BTREE". Versuchen Sie es vielleicht ohne das USING BTREE und sehen Sie, ob Sie immer noch dasselbe Verhalten sehen. (Oder entfernen Sie den Index ganz, um ihn zu testen. All dies hilft, das Problem einzugrenzen.)
Hoffe das hilft.
quelle
Versuchen Sie die Abfrage
quelle
Ich sehe etwas Interessantes im Tabellenlayout, das "Ich habe keine Lust zu zählen" ruft. Was ich sagen will, ist nur eine Ahnung.
Sie haben diese Abfrage zuvor ausgeführt
Führen Sie es als COUNT / GROUP BY aus
Sie sollten die definitiven Zählimpulse erhalten, die Sie suchten.
Aber warum werden die Zählungen für NULL und NOT NULL korrekt berechnet? Auch dies ist nur eine Vermutung.
Sie haben die Spalte
estimated_date
indiziert. Folgendes solltest du versuchen:Das ist kein Tippfehler. Ich möchte, dass du
SHOW INDEX FROM s_p;
vier (4) Mal rennst. Schau dir dieCardinality
Säule an. Seit der Tabelles_p
in InnoDB erwarte ich, dass die Kardinalitätsspalte jedes Mal anders ist. Warum?InnoDB erhält den Kardinalitätswert durch Schätzen (NO PUN INTENDED) durch Zählen über die BTREE-Seiteneinträge. Überprüfen Sie Ihre Systemvariable innodb_stats_on_metadata . Es sollte aktiviert sein. Wenn es bereits aktiviert ist, deaktivieren Sie es, und führen Sie die ursprünglichen Abfragen erneut aus, um zu prüfen, ob sich Verbesserungen ergeben. TUN SIE DAS NUR ALS LETZTES RESORT !!!
Anstelle dieser Abfragen:
Versuchen
Dies sollte Ihnen die Anzahl der Zeilen mit einem geschätzten Datum ungleich Null anzeigen.
Ein anderer Ansatz, mit dem Sie möglicherweise mit dieser Brute-Force-Abfrage mithilfe der ISNULL- Funktion experimentieren möchten :
Ich hoffe diese Vorschläge helfen !!!
quelle
Dies wird erwartet. Für eine Spalte, die nullwertfähig ist, ist eine 0 == NULL = "" und so weiter. Die erste Prüfung gibt also tatsächlich Zeilen zurück, in denen kein Datum festgelegt wurde oder deren Wahrnehmung analog zu "0 / NULL" ist.
quelle
0
ist niemals gleichNULL
. Leere Zeichenfolge (''
) ist nicht dasselbe wieNULL
, es sei denn, Sie arbeiten mit Oracle.