Twitterに書き殴ったのですが、流れてしまうので、一応こちらにもまとめておこうかと。
これって、何を数えているんでしたっけ?
— 坂井 恵(SAKAI Kei) (@sakaik) 2020年5月1日
mysql> SELECT COUNT(*);
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
コトの発端はちょっとした打ち間違いだったのですが、MySQL は FROM 書かなくても演算できます。こんな感じ。
mysql> SELECT 3; +---+ | 3 | +---+ | 3 | +---+ mysql> SELECT SQRT(64); +----------+ | SQRT(64) | +----------+ | 8 | +----------+
ここで、SELECT COUNT(*) とすると何が返ってくるのか。そう、 1 が返ってきます。
mysql> SELECT COUNT(*); +----------+ | COUNT(*) | +----------+ | 1 | +----------+
EXPLAIN取って、出てきた WARNING を見てみると、どうも COUNT(0) として解釈され、処理が行われている模様。
mysql> EXPLAIN SELECT COUNT(*); +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +-------+------+----------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------+ | Note | 1003 | /* select#1 */ select count(0) AS `COUNT(*)` | +-------+------+----------------------------------------------+ 1 row in set (0.00 sec)
じゃぁ、* は、FROMがないときはゼロ相当なのか、というと、そうでもない。
mysql> SELECT *; ERROR 1096 (HY000): No tables used
カッコ付ければいいってもんでもない。
mysql> SELECT (*); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*)' at line 1
念のため言っておくけど、no tables だからって、FROM dual をつければいいってもんでもない。
mysql> SELECT * FROM dual; ERROR 1096 (HY000): No tables used
と悩んでいるところに、神降臨。
それは SELECT COUNT(*) FROM DUAL だから 1 が返るのは普通な気がします。
— とみたまさひろ🍣🍺 (@tmtms) 2020年5月1日
dual 表は仮想的に1行だけ持ってるテーブルなので、1が正しいです。0行だと、select 123 from dual が何も返さなくなっちゃう。
— とみたまさひろ🍣🍺 (@tmtms) 2020年5月1日
結論。
『dual 表(MySQLでは通常、記述を省略)は、1件を返す』