3.3.4.8 行のカウント

データベースは、テーブルの中に、特定のタイプのデータがどの程度の頻度で現れるかという質問に答えるために使用されることがよくあります。たとえば、何匹ペットを飼っているのか、それぞれの所有者が何匹のペットを所有しているかを調べたり、または動物に対してさまざまな個体数調査を実施したりすることがあるでしょう。

ペットの総数をカウントすることは、pet テーブルには何行あるかという質問と同等です。このテーブルにはペットごとに 1 つのレコードが存在するからです。COUNT(*) は行数をカウントするため、ペットの数をカウントするクエリーは次のようになります。

mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

前に、ペットの所有者の名前を取得しました。COUNT() を使用して、各所有者のペットの数を調べることができます。

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Benny  |        2 |
| Diane  |        2 |
| Gwen   |        3 |
| Harold |        2 |
+--------+----------+

このクエリーは GROUP BY を使用して各 owner のすべてのレコードをグループ化しています。COUNT()GROUP BY とともに使用すると、さまざまなグループ化の下でデータの特徴を示すことができます。次の例では、ペットの個体数調査を実行するさまざまな方法を示します。

種ごとのペット数

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+

性別ごとのペット数

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex  | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

(この出力で、NULL は性別不明を示します。)

種と性別の組み合わせごとのペット数

mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | NULL |        1 |
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

COUNT() を使用するときにテーブル全体を取り出す必要はありません。たとえば、前のクエリーを犬と猫だけに対して実行する場合は、次のようになります。

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE species = 'dog' OR species = 'cat'
    -> GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
+---------+------+----------+

または、性別のわかっているペットについてのみ性別ごとのペット数を調べるには:

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE sex IS NOT NULL
    -> GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

COUNT() 値に加え、選択するカラムを指定する場合は、それらのカラムを GROUP BY 句で指定する必要があります。そうでない場合は、次のようになります。

  • ONLY_FULL_GROUP_BY SQL モードが有効である場合は、エラーが発生します。

    mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT owner, COUNT(*) FROM pet;
    ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
    with no GROUP columns is illegal if there is no GROUP BY clause
    
  • ONLY_FULL_GROUP_BY が有効でない場合、このクエリーはすべての行を 1 つのグループとみなして処理されますが、指定した各カラムに選択される値は不確定です。サーバーによって任意の行の値が自由に選択されます。

    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)
    

セクション12.19.3「MySQL での GROUP BY の処理」も参照してください。


User Comments
  Posted by Adrian Chapela Cordeiro on April 9, 2010
COUNT doesn't count NULL values, so if you are counting values by a field that has NULL values, that rows won't be counted by COUNT.

Example: I have the same table pet with two fields, owner and species and I have inserted one row with owner=NULL. The table has 6 rows, 2 dogs, 2 cats and 2 birds ;)

SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird | 2 |
| cat | 2 |
| dog | 2 |
+---------+----------+
SELECT species, COUNT(owner) FROM pet GROUP BY species;
+---------+--------------+
| species | COUNT(owner) |
+---------+--------------+
| bird | 2 |
| cat | 2 |
| dog | 1 |
+---------+--------------+
select * from pet;
+--------+---------+
| owner | species |
+--------+---------+
| Benny | bird |
| Diane | bird |
| Gwen | cat |
| Harold | cat |
| Adrian | dog |
| NULL | dog |
+--------+---------+

  Posted by Ryan Leadenham on August 18, 2011
As an extension to Adrian's comment about not counting NULL values, if you need to count the number of rows with the value of '0' for a field you will have to do an IF() statement inside the COUNT() which returns NULL, not '0', for rows you don't want to include in the count.

In the example above imagine there was a field named 'dead' for animals that have died, you could count the number of alive and dead animals for an owner like so:

SELECT owner, COUNT(*) AS total_pets, COUNT(IF(dead = '0', 1, NULL)) AS alive_pets, COUNT(IF(dead = '1', 1, NULL)) AS dead_pets FROM pet GROUP BY owner;
  Posted by Farrukh Shahzad on March 20, 2012
Use of formula expression like IF() can make MYSQL query optimizer to completely forget about the indexes applied on the table fields.

For optimization I recommend use of EXPLAIN before you are going to use the expression functions.
  Posted by Danyel Lawson on October 25, 2012
WHERE column != 0 OR other_column != '1'
Sign Up Login You must be logged in to post a comment.