質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

3637閲覧

MySQLでCASE式でカウントできない

yotsuba

総合スコア20

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2016/03/21 09:16

編集2016/03/21 10:11

Windows版のMySQL5.0.96を使っています。

指定したデータの件数をカウントしようと、テーブル内のCategoryの「野菜」「果物」
を指定しましたがカウントできませんでした。
原因はなにが考えられるでしょうか?

■total テーブル(※修正1)
+------+----------+------------+-------+-------+
| code | category | name | price | sales |
+------+----------+------------+-------+-------+
| 1001 | 果物 | りんご | 300 | 4800 |
| 1002 | 果物 | オレンジ | 150 | 4950 |
| 1003 | 果物 | バナナ | 420 | 2100 |
| 1004 | 果物 | イチゴ | 880 | 7920 |
| 1005 | 果物 | 桃 | 620 | 2480 |
| 1006 | 野菜 | ピーマン | 245 | 6615 |
| 1007 | 野菜 | 人参 | 198 | 3762 |
| 1008 | 野菜 | ほうれん草 | 98 | 2058 |
+------+----------+------------+-------+-------+

■実行したSQL文(※修正2-太線部分)
select count(category) as "総数",
sum( case category when '果物' then 1 else 0 end ) as "果物の数" ,
sum( case category when '野菜' then 1 else 0 end ) as "野菜の数"
from total;

■実行結果
+------+----------+----------+
| 総数 | 果物の数 | 野菜の数 |
+------+----------+----------+
| 8 | 0 | 0 |
+------+----------+----------+

■列の構造
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| code | char(4) | YES | | NULL | |
| category | varchar(20) | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| price | int(11) | YES | | NULL | |
| sales | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ああ、whenって書いてましたね。
select count(category) as "総数",
( select count() from total where category = '果物' ) as "果物の数" ,
( select count(
) from total where category = '野菜' ) as "野菜の数"
from total;
コードはこちらが正しいです。mysql5.6では動作確認しましたが5.0で動作するかは未知数

投稿2016/03/21 11:22

hirohiro

総合スコア2068

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirohiro

2016/03/21 11:24 編集

間違って新規投稿してしまいました.... 消せないのかな。 また2ptついてるし。この辺ちょっと欠陥っぽい。
yotsuba

2016/03/21 11:32

hirohiroさん 結果が正しく表示できました! mysql> select count(category) as "総数", -> ( select count(*) from total where category = '果物' ) as "果物の数" , -> ( select count(*) from total where category = '野菜' ) as "野菜の数" -> from total; +------+----------+----------+ | 総数 | 果物の数 | 野菜の数 | +------+----------+----------+ | 8 | 5 | 3 | +------+----------+----------+ 1 row in set (0.06 sec) こちらのほうがすっきりしていいですね。 countの使い方をもっと勉強します。 ありがとうございました!
hirohiro

2016/03/21 11:44 編集

ああ、もしヘビーに使うならちゃんとコスト計測したほうがいいと思いますよ。 こっちのコードは副問い合わせ含めて3回SQLを投げ、もう一方はDBへの問い合わせは1回ですがCASEでの振り分けを行います。(実際のところオプティマイザの性能次第ですが、昔のmysqlは頭悪いと評判だったように思います) データ件数が数十万件、毎分何回アクセスとかにならないならどっちでも問題無いとは重いますが....感覚的はCASEを使うほうが軽いような気はします。
yotsuba

2016/03/22 14:34

まだ勉強始めたばかりなので、コスト計測(パフォーマンス?)などはよくわかっていませんが、今後の課題にしたいと思います。 いろいろ教えて頂きありがとうございました。
guest

0

category登録名が'果物'や'果物'ではなく、' 果物'だったなどでしょうか?
固定長のカラムでも問題は起きないみたいなので、データ入力時にわざと前方に空白を入れていないと再現しないと思います。:参考

他にはSQL実行エディタとテーブルの文字コードが異なっていた等

投稿2016/03/21 09:29

編集2016/03/21 09:40
hirohiro

総合スコア2068

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yotsuba

2016/03/21 09:43

ありがとうございます。 データにスペースがあるとのご指摘ですね。 データの登録時には以下のように記述しました。 INSERT INTO total VALUES ('1001','果物','りんご',300, 4800), ('1002','果物','オレンジ',150, 4950), ('1003','果物','バナナ',420, 2100), ('1004','果物','イチゴ',880,7920), ('1005','果物','桃',620, 2480), ('1006','野菜','ピーマン',245, 6615), ('1007','野菜','人参', 198, 3762), ('1008','野菜','ほうれん草', 98, 2058); 念のため、テーブルのcategory を 果物→kudamono , 野菜→yasai というふうに update してからSQL文実行しましたがカウントはできませんでした。 (SQL文でも kudamono,yasai に変えています。)
yotsuba

2016/03/21 09:48

hirohiro さんへ 頂いた回答の2行目以降が見れていませんでした。 確認します。リンクありがとうございます。
hirohiro

2016/03/21 10:11 編集

あら。 こちらのサイト「https://paiza.io/」で以下のSQLを試した所、期待通り集計されるようです。バージョンが多少変わってもこの動作は崩れないと思うのですが... ---SQL create table food(id integer, category varchar(100), name varchar(100), price integer); INSERT INTO food VALUES ('1001','果物','りんご',300), ('1002','果物','オレンジ',150), ('1003','果物','バナナ',420), ('1004','果物','イチゴ',880), ('1005','果物','桃',620), ('1006','野菜','ピーマン',245), ('1007','野菜','人参', 198), ('1008','野菜','ほうれん草', 98); select count(category) as "総数", sum( case category when '果物' then 1 else 0 end ) as "果物の数" , sum( case category when '野菜' then 1 else 0 end ) as "野菜の数" from food; --- 所で質問文に掲載されているテーブルの要素は「code,category,name,price」の4つですが、コメント欄に掲載されたSQLでは項目が5つあるようです。 ずれて登録されているということはありませんか? select category from total;  で「果物」や「野菜」が抽出可能でしょうか? ※「INSERT INTO total VALUES 」とtotalへinsertしていますが、質問文に掲載されているテーブルはfoodのようです。もしかして違うテーブルにinsertしてしまったとか...
yotsuba

2016/03/21 10:18

hirohiroさん ご指摘ありがとうございます。最初の質問文に載せたテーブルが別のものでした。 質問文でテーブルとSQL文を修正しています。混乱させてすみません。 select 文を実行させた結果は以下のとおりです。 mysql> select category from total; +----------+ | category | +----------+ | 果物 | | 果物 | | 果物 | | 果物 | | 果物 | | 野菜 | | 野菜 | | 野菜 | +----------+ 8 rows in set (0.00 sec) mysql> この状態でも、結果は変わらず、以下のようになりました。 mysql> select count(category) as "総数", -> sum( case category when '果物' then 1 else 0 end ) as "果物の数" , -> sum( case category when '野菜' then 1 else 0 end ) as "野菜の数" -> from total; +------+----------+----------+ | 総数 | 果物の数 | 野菜の数 | +------+----------+----------+ | 8 | 0 | 0 | +------+----------+----------+ 1 row in set (0.00 sec) mysql> ※環境は WindowsXPマシン上のMySQL、MySQL Command Line Clientを使っています。XPマシンへはWindows7からリモートデスクトップ接続で操作しています。
hirohiro

2016/03/21 10:33 編集

mysql5.0系って相当古いですね。 もしかすると、group入れないとcount以外の集計ができないのかも知れません。
hirohiro

2016/03/21 10:30

select count(*) from total where category = '野菜'; もしこれが3になるなら、sum(case の文が動作しない可能性がありますね。 これが0になるなら、文字コードの問題かと思いますが、kudamonoにしても駄目だったそうですので、その可能性もなさそうです。 これらも動作するかどうかはわかりませんが他のコード select count(category) as "総数", ( select count(*) from total when category = '果物' ) as "果物の数" , ( select count(*) from total when category = '野菜' ) as "野菜の数" from total;
yotsuba

2016/03/21 11:18

hirohiroさん ありがとうございます。 実行結果は下のようになりました。 ************************************ mysql> select count(*) from total where category = '野菜'; +----------+ | count(*) | +----------+ | 3 | +----------+ 1 row in set (0.00 sec) ************************************ mysql> select count(category) as "総数", -> ( select count(*) from total when category = '果物' ) as "果物の数" , -> ( select count(*) from total when category = '野菜' ) as "野菜の数" -> from total; 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 'when category = '果物' ) as "果物の数" , ( select count(*) from total when categ' at line 2 mysql> ************************************ 補足ですが、文字コードの設定は以下のようになっています。 MySQLインストール後に、mi.ini を書き換えて UTF8→sjis にしています。 +--------------------------+-----------------------------------------------------+ | Variable_name | Value | +--------------------------+-----------------------------------------------------+ | character_set_client | sjis | | character_set_connection | sjis | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | sjis | | character_set_server | sjis | | character_set_system | utf8 | +--------------------------+-----------------------------------------------------+
yotsuba

2016/03/21 11:23 編集

試しに、記述を変えてみたところ、結果が表示されるようになりました。 (case category when のところ) mysql> SELECT COUNT(category) AS "総数", -> SUM( CASE -> WHEN category = '果物' THEN 1 -> ELSE 0 -> END ) AS "果物の数", -> SUM( CASE -> WHEN category = '野菜' THEN 1 -> ELSE 0 -> END ) AS "野菜の数" -> FROM total; +------+----------+----------+ | 総数 | 果物の数 | 野菜の数 | +------+----------+----------+ | 8 | 5 | 3 | +------+----------+----------+ 1 row in set (0.00 sec) hirohiroさんのご指摘の通り、  sum(case category ~  の記述だとダメなのかもしれません。
hirohiro

2016/03/21 11:26

動作したようでよかったです。 2008年付けのmysql5.1の新機能!みたいな記事があったので 5.0は相当古いみたいですね。最新バージョンとはお作法の違う部分がいろいろあるのだと思います。
yotsuba

2016/03/22 14:32

参考にしているテキストに載っているコマンド/関数が使えないとこまるので、 MySQL 5.5.47 へバージョンアップしました。 最初に載せたSQL文でも動作するようになりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問