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

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

ただいまの
回答率

90.37%

  • MySQL

    7306questions

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

  • SQL

    3159questions

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

【mysql】case文で条件に一致したら複数項目取得したい

解決済

回答 6

投稿

  • 評価
  • クリップ 0
  • VIEW 17K+

k499778

score 515

現在mysqlでデータ取得のコードを書いています。

質問があるのですが、
結論からいうと、

case文で条件に一致したら複数項目を取得するにはどのうようにすればいいでしょうか?

具体的な状況は次のとおりです。

料理テーブルに「食べ物フラグ」カラムがあり、1だと「野菜」、2だと「フルーツ」「お菓子」カラムを取得します。

そこでcase文を使って書こうとしているのですが、複数取得の方法がわかりません。

select
case 食べ物フラグ
when '1' then 野菜
when '2' then フルーツ,お菓子
else null
end
from 料理テーブル

のような書き方はできますでしょうか?

もしできないようであれば他の方法を教えていただけると助かります。
 

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • A.Ichi

    2016/08/01 20:09

    確認ですが、食べ物フラグの値が1の時、項目(野菜)の値を表示し、2の時は項目(フルーツ)と項目(お菓子)を表示すると言う意味でしょうか?

    キャンセル

  • k499778

    2016/08/01 21:40

    そうです

    キャンセル

回答 6

checkベストアンサー

+1

まず命題のSQLは不可能です

代替案として

create table 料理テーブル(id int not null primary key,野菜 varchar(20) null,フルーツ varchar(20) null,お菓子 varchar(20) null,食べ物フラグ tinyint);
insert into 料理テーブル values(1,'にんじん',null,null,1),(2,'じゃがいも',null,'じゃがりこ',1),(3,'きゅうり','きゅうり',null,2),(4,null,null,'きのこの山',2),(5,null,'バナナ','バナナ',2),(6,null,null,null,0);


に対して複数項目を得るときにはCONCATでひろうとか

select 
case 食べ物フラグ
when 1 then 野菜 
when 2 then CONCAT(COALESCE(フルーツ,''),',',COALESCE(お菓子,''))
else null
end AS 食べ物
from 料理テーブル;


しかしこれだとどちらかにしかデータがない場合中途半端なカンマがつくので
気持ち悪い、たとえばどちらか取ればいいなら

select 
case 食べ物フラグ
when 1 then 野菜 
when 2 then COALESCE(フルーツ,お菓子)
else null
end AS 食べ物
from 料理テーブル;

もしくは視点を変えてカラムは表示するけどNULLにするとか

select if(食べ物フラグ=1,野菜,null) AS 野菜
,if(食べ物フラグ=2,フルーツ,null) AS フルーツ
,if(食べ物フラグ=2,お菓子,null) AS お菓子
,食べ物フラグ
from 料理テーブル;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 22:06

    レコードごとに列数が変わることはSQLでもエクセルでもテーブルでも
    どう考えてもありえませんよね?
    上記例を利用した場合どういう結果がほしいのか提示してみてください
    ご自身が頭のなかで架空の結果を得ている可能性が高い

    キャンセル

  • 2016/08/01 22:07

    回答ありがとうございます。

    いろいろな方法があることが知れて本当に良かったです。

    他の方にも聞いているのですが、
    そもそもなぜこんなことを聞いているかというと、
    現在詳細設計をしていて
    「食べ物フラグが1のときは野菜項目を表示し、食べ物フラグが2のときはフルーツ項目、お菓子項目を表示する」という仕様があるのです。
    まだまだ経験が浅い私なのですが、それはSQLでどうにかするよりも普通画面側(HTML側)で条件分岐をかまして表示するっていう方が自然なのですかね?
    フラグも項目も全取得して。SQLでどうにかするのではなく、画面側で。
    テンプレートエンジンにタイムリーフを導入しているのでそのようなこともできると思いますし。

    もしお時間ございましたらご意見お聞かせ願えればと思います。

    キャンセル

  • 2016/08/01 22:10

    必要項目を得るということは、不必要項目を得ないということと同意ではありません。
    必要項目が列記されていれば、うけとったプログラム側で必要に応じて
    任意の項目を取得すればよいのです。

    キャンセル

  • 2016/08/01 22:13

    タイムラグが発生してしまい、コメント頂く前に返答してしまいました。

    そして今頂いたコメントで私は大きな気づきをすることができました。
    そういうことですよね!
    勝手にその仕様を見てSQLで条件分岐をしようとしていました。
    全取得してプログラム側で編集するような設計に致します。

    大変親身に回答していただきありがとうございました。また一歩成長することができました。ありがとうございます。SQLも勉強します。

    キャンセル

+1

where で食べ物フラグの条件を指定して、
各々のレコードを取得して
union all したら?
--- 追加 ---

yambejpさんの回答を見てなるほど!って思った。
ちなみに、自分はこんな感じで考えてた。

select 野菜 as item1,null as item2 from 料理テーブル where 食べ物フラグ=1
union all
select フルーツ as item1,お菓子 as item2 from 料理テーブル where 食べ物フラグ=2

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 22:04

    回答有り難うございます。
    まだまだSQL初心者で初歩的な質問をしてしまい申し訳ないです。

    union all という手もあるのですね!参考になります。

    そもそもなぜこんなことを聞いているかというと、
    現在詳細設計をしていて
    「食べ物フラグが1のときは野菜項目を表示し、食べ物フラグが2のときはフルーツ項目、お菓子項目を表示する」という仕様があるのです。
    まだまだ経験が浅い私なのですが、それはSQLでどうにかするよりも普通画面側(HTML側)で条件分岐をかまして表示するっていう方が自然なのですかね?
    フラグも項目も全取得して。SQLでどうにかするのではなく、画面側で。
    テンプレートエンジンにタイムリーフを導入しているのでそのようなこともできると思いますし。

    もしお時間ございましたらご意見お聞かせ願えればと思います。

    キャンセル

  • 2016/08/01 22:21

    そもそも的な話なら、KotoriMaturiさんが指摘されているように
    「なんでそんなテーブルになってんの?」ってとこですよね。
    何某かの意図があってそういう造りになっているのなら、
    それに沿った処理の仕方はおのずと決まってくるでしょう。

    で、それは部外者の我々では分からないってことです。
    技術的に、一般的にどういう方法があるかってのは
    いくらでも提示できますが、それが「そもそも」の方針に
    合致していなければ混乱を生むだけでしょう。

    いますべきなのは、ここに質問することではなく
    データベースの設計者と話すことだと思います。

    ちなみに、自分だったら素直に全項目を(SQLで)取得して
    プログラム側でいいようにする方法をとるかなあ。

    キャンセル

  • 2016/08/01 22:27

    返答ありがとうございます。

    そうなんですね。あまりないテーブル構造なのでしょうか。
    自分自身まだまだそういうところに気づけるレベルではないので仕様通り落とし込んでいました。

    ただプログラム側で行うのが一般的のようですね。
    takasima20さんもおっしゃっている通りそのようにして進めていきたいと思います。
    アドバイス頂きありがとうございました。

    キャンセル

+1

select 
case 食べ物フラグ 
when '1' then 野菜 
when '2' then concat(ifnull(フルーツ, ''), ifnull(お菓子, '')) 
else null 
end 
from 料理テーブル


こういうことかしら?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 22:05

    回答有り難うございます。
    私も最終手段としてconcatで文字連結する手も考えていました。
    アドバイス頂き感謝です。

    他の方にも聞いているのですが、
    そもそもなぜこんなことを聞いているかというと、
    現在詳細設計をしていて
    「食べ物フラグが1のときは野菜項目を表示し、食べ物フラグが2のときはフルーツ項目、お菓子項目を表示する」という仕様があるのです。
    まだまだ経験が浅い私なのですが、それはSQLでどうにかするよりも普通画面側(HTML側)で条件分岐をかまして表示するっていう方が自然なのですかね?
    フラグも項目も全取得して。SQLでどうにかするのではなく、画面側で。
    テンプレートエンジンにタイムリーフを導入しているのでそのようなこともできると思いますし。

    もしお時間ございましたらご意見お聞かせ願えればと思います。

    キャンセル

+1

回答出揃ってるので蛇足ですが…

提示されてるようなSQLは記載不可なのでいくつかの代替案で対処する必要があります。

代替案について

要件次第で、
以下のアプローチのうちいずれかを取る形になるのかなと思います。

①CASE式内でCOALESCEを用いる
②結果の文字列を結合して取得する
③取得カラムを明示的に分ける

①が採用できる前提条件は、

  • どちらか一方の値だけが出力されることが許容できること(フルーツとお菓子は背反で取得される)
  • どちらか一方が優先出力されるのが許容できること(どちらも値がある場合は片方が優先取得される)

③が採用できる条件は、

  • 出力結果としてカラムが増えることが許容できること(個人的には結果を混ぜるよりはカラムは分けてた方がメンテしやすい気はします)
    出力の仕方は区分値に該当するなら登録値、なければNULLとか空文字とか…

②については上記2つの選択肢が取れない場合に採用する手段かなと思います。

コードは他の方の分で出揃ってるかなと思いますので当方からの掲示は割愛します。

おまけの話

上記のようなシチュエーションは、
1度限りとかであれば特殊要件なので、あまり心配しなくて良いかと思いますので以下読み飛ばしてください。

ですが万一同じような処理が、
色々な機能で必要となるんですよという状況であれば、テーブル構造の見直しが一番の最適解になることもあり得ます。

SQLやPGでごちゃごちゃしなければな
らないケースというのは、
テーブル構造の歪みに起因することもしばしばです。

やりたいこととして提示していただいてるサンプルを見る限り、
フルーツとお菓子の区別がテーブル保存時に消えてしまっているように見受けられます。

データベースとのやりとりの複雑度は、
こういった情報の欠落が起これば起こるほど飛躍的に上がるものなので、
もし今回のような処理ケースが今後も出てくる、あるいは既に散在しているのでしたら、テーブル定義の見直しを進言しても良いかもしれません。

個人的には食べ物区分は種別ごとに一意に振られ、
でもフルーツとお菓子どっちも取ってこないいけないよという要件があるなら、
もう一個それを示すフラグとか区分なりを追加する方が後々すっきりするかなとも思ってます。

補足

CASE式について補足。
THEN句の後の値のデータ型が一致することが要求されます。

以下は文字列の場合

CASE col1
   WHEN '1' THEN '文字列1'
   WHEN '2' THEN '文字列2'   -- 一つ目文字なら2つ目も文字で統一
   ELSE NULL                -- ただしNULLはOK
END

以下は数値

CASE col1
   WHEN '1' THEN 100
   WHEN '2' THEN 5          -- 一つ目数値なら2つ目も数値で統一
   ELSE NULL                -- ただしNULLは(ry
END

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 21:51

    回答有り難うございます。
    ご回答いただいた中に「取得カラムを明示的に分ける」というのがあるのですが、
    こちらはどのようにするのでしょうか?

    もしかすると私がcase文と言ってしまったから逆にミスリードしてしまったかもしれません。
    結果を混ぜるよりむしろカラムを分けて取得したいと思っています。

    結果として
    「食べ物フラグ」が1のとき、「野菜」の項目が、「食べ物フラグ」が2のとき、「フルーツ」の項目と「お菓子」の項目を取得したいと思っています。

    なのでcase文にこだわりはなく、目的を達成できればやり方はなんでも大丈夫です。

    それでもやはりそのようなことはできないのでしょうか?

    キャンセル

  • 2016/08/01 21:58

    yambejpさんの4つ目のSQLが参考となります。
    後、asahina_devさんのでも実現できそうですね。

    キャンセル

  • 2016/08/01 22:17

    回答有り難うございます。
    SQLでもがんばれば実現できるとわかりました。
    ただ画面側で編集するという視点に気づくことができ、SQLでは前取得し、Viewで編集する方向で行きたいと思います。
    貴重なご意見ありがとうございました。
    また一歩進むことができました。感謝しています。

    キャンセル

+1

ネタ系SQLとすればこのあたりだね

SELECT
     (CASE WHEN 食べ物 = 1 THEN 野菜
           WHEN 食べ物 = 2 THEN 果物
           ELSE NULL END) AS ITEM_1,
     (CASE WHEN 食べ物 = 2 THEN 菓子
           ELSE NULL END) AS ITEM_2
FROM
    テーブル名
WHERE
    条件式

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 22:08

    回答ありがとうございます。

    頑張ればそういう方法でもできるのですね!いろいろと勉強になります。

    他の方にも聞いているのですが、
    そもそもなぜこんなことを聞いているかというと、
    現在詳細設計をしていて
    「食べ物フラグが1のときは野菜項目を表示し、食べ物フラグが2のときはフルーツ項目、お菓子項目を表示する」という仕様があるのです。
    まだまだ経験が浅い私なのですが、それはSQLでどうにかするよりも普通画面側(HTML側)で条件分岐をかまして表示するっていう方が自然なのですかね?
    フラグも項目も全取得して。SQLでどうにかするのではなく、画面側で。
    テンプレートエンジンにタイムリーフを導入しているのでそのようなこともできると思いますし。

    もしお時間ございましたらご意見お聞かせ願えればと思います。

    キャンセル

  • 2016/08/01 22:13

    回答でもいってるとおり SQLでやるのは「ネタ」です。
    通常は画面(VIEW)ですね

    キャンセル

  • 2016/08/01 22:15

    返答頂きありがとうございます。

    そうですよね。それに気づかせていただくことができました。
    ありがとうございました。

    キャンセル

+1

すでにベストアンサーが出てますが

UNION ALLで1レコードごとに取得して
表示側で縦でも横でも好きなように表示できるようにしたらいいんじゃないでしょうか?

SELECT 野菜
FROM 料理テーブル
WHERE 取得条件
AND 野菜フラグ = 1
UNION ALL
SELECT フルーツ
FROM 料理テーブル
WHERE 取得条件
AND 野菜フラグ = 2
UNION ALL
SELECT お菓子
FROM 料理テーブル
WHERE 取得条件
AND 野菜フラグ = 2

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/03 07:44

    回答ありがとうございます。

    確かにこれだと出力できますね!勉強になりました。
    ありがとうございます。

    キャンセル

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

  • ただいまの回答率 90.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • MySQL

    7306questions

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

  • SQL

    3159questions

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