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

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

ただいまの
回答率

90.51%

  • PHP

    20343questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    5854questions

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

正規化した構成のデータの呼び出し(検索)について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 216

chapp

score 158

お世話になります。PHPでMySQLを使ったウェブサービスを作っているのですが、以下のような正規化を行った構成のデータは、どのようなSQL文となるのかイメージ出来ずに質問いたします。

memberテーブル
no   name old  sex
1   田島  21  woman
2   佐藤  32  man
3   菊池  26  woman

kudamonoテーブル
no   name
1   いちご
2   みかん
3   バナナ
4   りんご
5   ぶどう

likeテーブル(メンバーが好きな果物を登録。memberテーブルのnoとmember_no、kudamonoテーブルのnoとkudamono_noは紐づいている)
no member_no kudamono_no
1    1     1
2    1     3
3    2     2
4    3     1
5    3     4
6    3     5

このテーブル構成にて、田島のデータは21歳の女性、好きな果物はイチゴとバナナです。

このような構成のテーブルで、年齢の範囲や性別、好きな果物をチェックボックスやセレクトボックスで選択し、該当するメンバーを呼び出したいと考えています。

ここで質問です。対象となる基本のテーブルがmemberテーブルかとは思うのですが、好きな果物はメンバー1人に対して複数あるので、負担なく検索するにはどのようなSQLとなるのかがイメージ出来ません。

以前、この果物は、memberテーブル内にカラムを設け、「ばなな,いちご,ぶどう」といった形で保存していたのですが、正規化した方が良いとのアドバイスをいただき今回のような構成にしたものの、今度は呼出す際の負担のないSQLに困っている次第です。

お忙しい中恐縮ですが、ご指南のほどよろしくお願いいたします。

■■ 追加情報 ■■
実際のテーブル構成は以下の通りです。
質問ではイメージしやすいようにと個人が好きな果物を例えにしていますが、実際は不動産物件情報で、それに付随する、「駅チカ物件」「ペット可」「デザイナーズ物件」などです。

ですので、

memberテーブル ⇒ property_dataテーブルであり(※)

kudamonoテーブル ⇒ osusumeテーブルであり

likeテーブル ⇒ property_data_osusumeであります。

※不動産物件という事ありカラムが多数あるので多くを省略しています。

これら構成の元、方位が西、または南西向きで、3LDK、ペット可で駅チカ物件と検索した際、該当する物件を抽出したいと考えたとき、例の果物に当たるosusumeが、チェックボックスでn個を検索条件とした場合、どのようなSQLになるのか?悩んでいるところです。

CREATE TABLE `property_data` (
  `data_no` int(11) NOT NULL,
  `data_corporate_user_no` int(11) NOT NULL,
  `data_cate_b_no` int(11) NOT NULL,
  `data_cate_m_no` int(11) NOT NULL,
  `data_pr` varchar(255) NOT NULL,
  `data_bukkenn_name` varchar(255) NOT NULL,
  `data_train1` varchar(64) NOT NULL,
  `data_train_station1` varchar(64) NOT NULL,
  `data_train_station_toho1` int(11) NOT NULL,
  `data_addr1` varchar(128) NOT NULL,
  `data_addr2` varchar(128) NOT NULL,
  `data_addr3` varchar(255) NOT NULL,
  `data_houi` enum('','北','北東','東','南東','南','南西','西','北西') NOT NULL,
  `data_madori1` varchar(16) NOT NULL,
  `data_madori2` enum('ワンルーム','K','DK','LK','LDK','SK','SDK','SLK','SLDK') NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- テーブルのデータのダンプ `property_data`
--

INSERT INTO `property_data` (`data_no`, `data_corporate_user_no`, `data_cate_b_no`, `data_cate_m_no`, `data_pr`, `data_bukkenn_name`, `data_train1`, `data_train_station1`, `data_train_station_toho1`, `data_addr1`, `data_addr2`, `data_addr3`, `data_houi`, `data_madori1`, `data_madori2`) VALUES
(20, 12, 1, 1, '駅近、ファミリータイプ物件!通り沿いで交通に便利なの物件です。', 'サニーレジデンス301', 'JR上越線', '長岡', 15, '新潟県', '長岡市', '旭町2丁目3-31', '東', '3', 'DK'),
(21, 12, 1, 1, '駅近、ファミリータイプ物件!通り沿いで交通に便利なの物件です。', 'サニーレジデンス402', 'JR上越線', '長岡', 15, '新潟県', '長岡市', '旭町2丁目3-25', '南西', '3', 'DK'),
(22, 13, 2, 10, 'ファミリー向けです!', 'エヌステージ似弐号館', 'JR弥彦線', '北三条', 2, '新潟県', '三条市', '本町1-3', '東', '4', 'LDK'),
(23, 13, 2, 10, 'ファミリー向けの物件です!', 'エヌステージ壱号館', 'JR弥彦線', '北三条', 10, '新潟県', '三条市', '本町1-3-17', '南東', '4', 'LDK'),
(24, 14, 1, 4, 'アスファルト、街灯、屋根付きのセキュリティーの高い駐車場', 'アテンド駐車場', 'JR上越線', '長岡', 20, '新潟県', '長岡市', '土合5丁目10-17', '北', '3', 'DK'),
(25, 12, 1, 1, 'エントランスが貴方の行き帰りをおもてなしします', 'Nステージ', 'JR信越本線(直江津~新潟)', '亀田', 40, '新潟県', '新潟市江南区', '二本木4丁目5-37', '南', '2', 'K'),
(26, 12, 2, 12, '広々した憧れの一軒家 二世帯でも対応可能な広さです', '三和区錦 一軒家', '北越急行ほくほく線', '大池いこいの森', 50, '新潟県', '上越市', '三和区錦1180-4', '南東', '5', 'LDK'),
(27, 14, 1, 1, '加治川のせせらぎ日頃の疲れを癒してくれます', 'ライフル', 'JR羽越本線', '新発田', 5, '新潟県', '新発田市', '豊町2丁目9-1', '北東', '3', 'DK'),
(29, 12, 2, 12, '広々した憧れの一軒家 二世帯でも対応可能な広さです', '三和区錦 一軒家', '北越急行ほくほく線', '大池いこいの森', 25, '新潟県', '上越市', '三和区錦1180-1', '南', '5', 'LDK'),
(30, 13, 2, 17, '想定利回り10%強! 現況満室の高収益物件!', 'エヌステージ似弐号館', 'JR上越線', '越後堀之内', 2, '新潟県', '三条市', '本町1-3', '南', '4', 'LDK');
CREATE TABLE `osusume` (
  `osusume_no` int(11) NOT NULL,
  `osusume_name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- テーブルのデータのダンプ `osusume`
--

INSERT INTO `osusume` (`osusume_no`, `osusume_name`) VALUES
(19, 'お風呂広い'),
(7, 'シニア(60歳以上)入居可'),
(22, 'デザイナーズ物件'),
(13, 'ファミリー向け'),
(17, 'フリーレント'),
(9, 'ペット可'),
(12, 'ルームシェア可'),
(21, 'ロープライス・フローライフ'),
(11, '事務所利用可'),
(6, '二人入居可'),
(14, '保証人不要'),
(1, '女性限定'),
(8, '子供可'),
(4, '学生可'),
(18, '更新料不要'),
(10, '楽器可'),
(3, '法人可'),
(2, '男性限定'),
(20, '訳アリ物件'),
(23, '駅チカ物件');
CREATE TABLE `property_data_osusume` (
  `property_data_no_osusume` int(11) NOT NULL,
  `property_data_data_no_osusume` int(11) NOT NULL,
  `property_data_osusume_no` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- テーブルのデータのダンプ `property_data_osusume`
--

INSERT INTO `property_data_osusume` (`property_data_no_osusume`, `property_data_data_no_osusume`, `property_data_osusume_no`) VALUES
(1, 1, 1),
(2, 1, 7),
(3, 1, 12),
(4, 2, 22),
(5, 2, 3),
(6, 2, 8),
(7, 3, 12),
(8, 3, 18),
(9, 4, 22);
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • Kosuke_Shibuya

    2018/07/03 22:52

    CREATE文とサンプルデータのINSERT文を提示してください。

    キャンセル

  • mts10806

    2018/07/04 09:36

    MySQLのみの回答で問題ないのでしょうか。

    キャンセル

  • mts10806

    2018/07/04 09:37

    また、「アドバイスをいただき~~~」の結果、実際に自身で組んでみたコード(SQLだけでも)も提示してください。

    キャンセル

回答 3

checkベストアンサー

+3

こういう場合は、テーブル結合(join)というのを使います。
「いちごかバナナが好きな女性」を探すなら

SELECT
    m.*
FROM
    member AS m
INNER JOIN
    member_kudamono AS mk
    ON
        m.no = mk.member_no
INNER JOIN
    kudamono AS k
    ON
        mk.kudamono_no = k.no
WHERE
    k.name IN ('いちご', 'バナナ')
    AND m.sex = 'woman'

です。
※質問文では「like」テーブルとなっていたところを「member_kudamono」テーブルに改名しています(SQLにおいて、おそらくlikeは予約語なので、使い勝手&可読性が悪くなるため)。
テーブル構造は「like」テーブルと同様です。

ただ、チェックボックス等で選ばせるのであれば、kudamonoのnameを表示、noをチェックボックスのvalueにしておけば、kudamonoのjoinは必要なくなります。

SELECT
    m.*
FROM
    member AS m
INNER JOIN
    member_kudamono AS mk
    ON
        m.no = mk.member_no
WHERE
    mk.id IN (1, 3)
    AND m.sex = 'woman'

質問へのコメントを受けて……。

すみません、回答が遅くなりました。
上記2つめのSQLがエラーになった件については、こちらで提示したSQLが誤っていたので訂正させていただきました( k.name IN ('いちご', 'バナナ')  ⇒ mk.id IN (1, 3) )。大変失礼いたしました。

もう一つのSQLでデータが取れなかった原因は調査しておりませんが、今回、実際のテーブルを提示していただいたので、そちらを元に改めて説明させていただきます。

条件が「OR」でなく「AND」とのことですので、この場合は(データ量が多い場合、若干速度面で問題はありそうですが)EXISTSを使うと可読性の良いSQLができます。

-- 事前準備SQL(テストデータに「ペット可、かつ、駅チカ物件」が存在しなかったので、テストデータを追加)
INSERT INTO  property_data_osusume (
property_data_no_osusume,
property_data_data_no_osusume,
property_data_osusume_no
)
VALUES
('10',  '20',  '9'),
('11',  '20',  '23'),
('12',  '21',  '9'),
('13',  '21',  '23')
;
-- 検索SQL
-- 条件:方位が西、または南西向きで、3DK、ペット可で駅チカ物件
-- ※元の条件では「3LDK」と書かれていましたが、テストデータに「3LDK」のデータが無かったので、3DKに変更しています。
SELECT
    p.*
FROM
    property_data AS p
WHERE
    p.data_houi IN ('西', '南西')
    AND
    (p.data_madori1 = '3' AND p.data_madori2 = 'DK') 
    AND
    EXISTS(
        SELECT
            *
        FROM
            property_data_osusume AS po
        INNER JOIN
            osusume AS o
            ON
                po.property_data_osusume_no = o.osusume_no
        WHERE
            p.data_no = po.property_data_data_no_osusume
            AND
            o.osusume_name = 'ペット可'
    )
    AND
    EXISTS(
        SELECT
            *
        FROM
            property_data_osusume AS po
        INNER JOIN
            osusume AS o
            ON
                po.property_data_osusume_no = o.osusume_no
        WHERE
            p.data_no = po.property_data_data_no_osusume
            AND
            o.osusume_name = '駅チカ物件'
    )


 
 
 
なお、多少可読性を犠牲にしてもいいから、とにかく速いSQLを!ということであれば、下記のような方法もあります。

-- 検索SQL
-- 条件:方位が西、または南西向きで、3DK、ペット可で駅チカ物件
-- ※元の条件では「3LDK」と書かれていましたが、テストデータに「3LDK」のデータが無かったので、3DKに変更しています。
SELECT
    p.*
FROM
    property_data AS p
INNER JOIN
    property_data_osusume AS po
    ON
        p.data_no = po.property_data_data_no_osusume
INNER JOIN
    osusume AS o
    ON
        po.property_data_osusume_no = o.osusume_no
WHERE
    p.data_houi IN ('西', '南西')
    AND
    (p.data_madori1 = '3' AND p.data_madori2 = 'DK') 
    AND
    o.osusume_name IN ('ペット可', '駅チカ物件')
GROUP BY
    p.data_no
HAVING
    COUNT(*) = 2 -- o.osusume_nameのINの中に設定した値の数

解説:
INで「ペット可、または、駅チカ物件」としているので、いったんJOIN結果として

data_no osusume_name
------- ------------
21      ペット可
21      駅チカ物件

が取得できる
⇒data_noでGROUP BYする
⇒data_no=21のcountは2となる
⇒HAVING COUNT(*) = 2としているので、条件に合致するレコードとなり、取得できる

こちら、「ペット可」しか条件に合致しない物件の場合(仮にdata_no=99とする)、

data_no osusume_name
------- ------------
99      ペット可
が取得できる
⇒data_noでGROUP BYする
⇒data_no=99のcountは1となる
⇒HAVING COUNT(*) = 2としているので、条件に合致しないレコードとなり、取得できない

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/06 16:07

    nakさま

    ご親切なアドバイスをありがとうございます。
    また、SQLのご提示、重ねて御礼申し上げます。

    ご提示して下さったSQLをphpMyAdminにて実行しているのですが、結果が返ってきません(0件表示)

    また、2つ目のSQLを実行すると、以下の表記のもとエラーとなってしまいます。

    #1054 - 列 'k.name' は 'where clause' にはありません。

    left joinはよく使うので、親しみやすい?内容ですが、
    k.name IN ('いちご', 'バナナ')や、 k.name IN (1, 3)の箇所など、普段触ることない内容なので、お教えいただいたソースのどこが原因で動かないのか?お教えいただければありがたいです。

    キャンセル

  • 2018/07/09 13:19

    大変遅くなりましたが、回答を修正いたしましたのでご確認をお願いいたします。

    なお、気になった点として……。
    例として新たに提示していただいたテーブルですが、プライマリキーもインデックスも貼られていないようです。
    「テストデータだから省いた」ということであれば良いのですが、そうでないなら、最低限プライマリキーは貼ったほうが良いと思います(インデックスはお好みで)。

    プライマリキー(=主キー)とインデックスについての説明
    ※Accessに関する説明ページですが、概念自体はMySQLでも一緒です。
    https://www.nishi2002.com/4002.html

    MySQLで主キー(=プライマリキー)やインデックス等を追加する方法
    http://tech.pjin.jp/blog/2017/05/31/mysql-key-sql1/

    キャンセル

  • 2018/07/14 15:54 編集

    nakさま

    お世話になっております。まずはもって、お礼のお返事が出来なかったことお詫びいたします。
    送信したつもりでしたが、きちんと送信が出来ていなかったようで、この状況に昨夜気づいた次第です。ご親切にご対応いただいているにも関わらず、申し訳ございませんでした。

    さて、未だ上手く行っていない状況なのですが、新たにご教示いただいた、EXISTS()を使って幾度も試しているのですが、ファミリー向け、フリーレント、ペット可、駅チカ物件など、検索条件として複数あるうち1つの場合はきちんと結果が返ってくるのですが、複数選択した場合データを抽出することが出来ません。

    以下は、実際に呼び出している際のSQL(WHERE以下の部分)です。

    また、以下のソースにGroup byを設けていますが、これをしないと、同じデータが羅列してしまうためこのような記述を行っています。

    そもそも問題ありな記述なのか?と不安もアリ書き残しました。

    これまで、多くの説明を頂いているため恐縮ですが、引き続き、ご指導いただければ幸いです。
    よろしくお願いいたします。

    1つの場合
    WHERE property_data.data_cate_m_no = '1' AND property_data.data_chintai_price >= 0 AND property_data.data_addr2 IN ('新潟市北区','長岡市') AND property_data.data_update_plan_date >= '2018-07-14' AND property_data.data_state = '' AND corporate_user.corporate_state = ''
    AND
    EXISTS( SELECT * FROM property_data_osusume AS PDO INNER JOIN osusume AS O ON PDO.property_data_osusume_no = O.osusume_no WHERE property_data.data_no = PDO.property_data_data_no_osusume AND osusume_no = '3') GROUP BY data_no ORDER BY property_data.data_update_plan_date DESC LIMIT 0, 20;


    複数(2つ)の場合
    WHERE property_data.data_cate_m_no = '1' AND property_data.data_chintai_price >= 0 AND property_data.data_addr2 IN ('新潟市北区','長岡市') AND property_data.data_update_plan_date >= '2018-07-14' AND property_data.data_state = '' AND corporate_user.corporate_state = '' AND
    EXISTS( SELECT * FROM property_data_osusume AS PDO INNER JOIN osusume AS O ON PDO.property_data_osusume_no = O.osusume_no WHERE property_data.data_no = PDO.property_data_data_no_osusume AND osusume_no = '3')
    AND
    EXISTS( SELECT * FROM property_data_osusume AS PDO INNER JOIN osusume AS O ON PDO.property_data_osusume_no = O.osusume_no WHERE property_data.data_no = PDO.property_data_data_no_osusume AND osusume_no = '2')
    GROUP BY data_no ORDER BY property_data.data_update_plan_date DESC LIMIT 0, 20;

    キャンセル

  • 2018/07/14 16:29

    ご丁寧にコメントありがとうございます。恐縮です。

    さて、

    > ファミリー向け、フリーレント、ペット可、駅チカ物件など、検索条件として複数あるうち1つの場合はきちんと結果が返ってくるのですが、複数選択した場合データを抽出することが出来ません。

    とのことですが、何点か確認させてください。

    確認1-1.「ペット可」と「駅チカ物件」の2つが選択されている場合、「ペット可、かつ、駅チカ物件」をご所望ですか?それとも、「ペット可、または、駅チカ物件」をご所望ですか?

    (1-1への回答が「ペット可、かつ、駅チカ物件」だった場合のみ)
    確認1-2.
    先日、こちらで提示させていただいた「方位が西、または南西向きで、3DK、ペット可で駅チカ物件」のSQLは、想定どおりの動作になりましたか?
    ※本物のデータではなく、chappさんが質問欄に貼ってくださったテストデータ&私が回答欄で追加したテストデータに対して、「方位が西、または南西向きで、3DK、ペット可で駅チカ物件」を探すSQLを実行してみてください。

    確認2.
    動作しないSQLのWHERE句部分を頂戴いたしましたが、実際に動くSQLで動作確認をさせていただきたいため、WHERE句以外も含めた「SQL全文(=そのまま動かせるSQL)」をいただけますと幸いです。

    ---

    > また、以下のソースにGroup byを設けていますが、これをしないと、同じデータが羅列してしまうためこのような記述を行っています。

    回答修正後に書かせていただいたSQLの場合、テーブルJOINをしていないので、同じデータは羅列しない想定でした。
    この点につきましては、いったん「確認2」にてSQL全文を拝見させていただいてからの回答とさせてください。

    キャンセル

  • 2018/07/14 19:36 編集

    nakさま

    お世話になっております。恐縮しながらも、実際に作っている構成をそのままアップしようと、テストをしながら準備していたところ、EXISTS()を生成するスクリプトに不備があること確認いたしました。
    誤った値が書き込まれ、結果的に正常な動きになっていなかったのが原因でした。

    nakさまのお返事が無かったら、誤りに気付かなかったと思います。ありがとうございます!

    それと、GROUP BYの件ですが、先のお返事にある「テーブルJOINをしていないので」からして、「テーブルをJOINしている場合は必要である」と認識で宜しかったでしょうか?

    この度の質問は簡素化するために無駄と思われるテーブルは省いてご説明したのですが、実際は複数のテーブルをJOINしています。

    実際のテーブル構成をあげることに問題はありませんが、そこそこの数になるので申し訳なくて・・・
    最後にGROUP BYの疑問以外は解決いたしました。最後にもう1点、ご教示いただければ幸いです。
    よろしくお願いいたします。

    キャンセル

  • 2018/07/15 12:10

    お疲れ様でした!

    > それと、GROUP BYの件ですが、先のお返事にある「テーブルJOINをしていないので」からして、「テーブルをJOINしている場合は必要である」と認識で宜しかったでしょうか?

    はい、JOIN対象のテーブルのデータが1対Nになる場合は必要かと思います(1対1の場合はGROUP BYしなくても問題はありません)。
    なお、別解として「GROUP BYではなく、DISTINCTを使う」という方法もありますが……どちらの方法でも期待された結果になると思いますので、お好きなほうをご利用ください。

    追伸:
    以下、今回のQAの「改善提案」です。
    今後の質問の際の参考になれば幸いです(クレームではありませんので、その点ご理解ください)。

    ・質問時、仕様は(決まっているのであれば)細かいところも含めて明確にする。
    →回答の変遷を見ていただいたのでおわかりかと思いますが、「女性、かつ、イチゴ"と(=AND)"バナナが好き」と「女性、かつ、イチゴ"か(=OR)"バナナが好き」では、発行するSQLが全く異なります。
     SQLだけでなく、プログラムの場合も「一見似たような条件だが、プログラムに落とすと全く違うコートになる」こともありますので、質問の時点で仕様が明確なのであれば、明記していただいたほうが、最初から「期待どおりの回答」がつきやすくなると思います。

    ・質問文中で提示している内容を元に話をできるようにする。
    →「実データでやってみたらうまくいかない」「実はSQLを組み立てる処理の部分に問題が……」というのは、回答者側の環境では再現不能です(情報がないため)。
     質問者と回答者が同じ土俵で話をできるようにしていただけると良いかと思います。
     
     今回の場合、提示していただいているのは「テストデータと仕様」、質問内容は「どのようなSQL文となるのか」なので、まずは「テストデータに対して、回答されたSQLを使い、期待した結果が取得できるかどうか(条件文等を、回答されたSQLを元に自分で変えてみたりするのは可)」を(PHPのプログラム経由ではなく)SQL単体で確認していただいて問題がなければ、「この質問」としてはゴールに到達したことになるのかな、と思いました。
     
     その後、実データに対して、回答を元に(プログラム経由ではなく手作業で)作成したSQLをテストしてみる→うまくいったらPHPのプログラムに組み込んでテストする、という手順で作業していけば、ご自身で調査をされる時も、どの部分に不具合があるのか判断しやすいかと。
     もし、「テストデータではうまくいったが、実データへのSQL発行時だけ、どうしても期待した結果にならない」のであれば、実データ(全テーブルの各数レコードずつを抜粋したもの)を元にした質問を改めて立てれば良いですし、「実データへのSQLも成功したが、PHPに組み込んだ時だけうまくいかない」のであれば、PHPのプログラムを含めた質問を立てれば良いと思います。

    キャンセル

  • 2018/07/15 21:53

    nakさま

    お世話になっております。お休みのところ、ご丁寧なアドバイスをありがとございます。

    Group Byの件、ありがとうございます。認識通りで安心いたしました。

    また、質問の内容の件、仰る通りですね。この度の一連のやり取りの中で、至らぬ点を気付かされました。ご親切からくるご指摘と受け止めております。

    以上、改めて、この度の回答、ありがとうございました。
    ソースだけでなく、それぞれに説明を頂けたことで理解も深まり、とても感謝しています。
    長々とお付き合いいただき、ありがとうございました!

    キャンセル

0

こうしてみてください

create table member(uid int primary key,uname varchar(20),old int ,sex int);
insert into member values
(1,'田島',21,2),
(2,'佐藤',32,1),
(3,'菊池',26,2);

create table kudamono(kid int primary key,kname varchar(20));
insert into kudamono values
(1,'いちご'),
(2,'みかん'),
(3,'バナナ'),
(4,'りんご'),
(5,'ぶどう');

create table member_kudamono(xid int primary key,uid int,kid int);
insert into member_kudamono values
(1,1,1),
(2,1,3),
(3,2,2),
(4,3,1),
(5,3,4),
(6,3,5);
  • 検索
select t1.uid,t1.uname,t4.kgroup from member as t1
inner join (
select t2.uid,group_concat(kname) kgroup
 from member_kudamono as t2
inner join kudamono as t3 on t2.kid=t3.kid
group by uid
) as t4 on t1.uid=t4.uid

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/06 19:51

    yambejpさま

    ご親切なアドバイスをありがとうございます。
    また、カラム名を変えてのcreatet文をありがとうございます。

    ご提示いただいたselect文を実行しているのですが、年齢や性別の他、チェックベックスなどで果物をN個を絞込検索するにはどのようなWHERE文になるのでしょうか?試しているのですが、いずれもエラーとなってしまって・・・

    引き続き、ご指導頂戴できたら幸いです。
    よろしくお願いいたします。

    キャンセル

0

エスパー回答です
勝手に、「動的に where 条件を追加したい」という質問と読み替えました。

その場合、if で条件分岐し、sql 文とバインドする変数を追加する事で実現できます。

エスパーな上に、回答はコピペですが参考まで。
条件検索におけるプリペアドステートメントの使用
escape_wildcard()の実装は、本を買って確認してくださいw

answerer ockeghem [12月18日 17:19]
検索条件が動的に変わる場合、プレースホルダ(プリペアードステートメント)をどう使って良いかはよくある質問だと思います。「体系的に学ぶ 安全なWebアプリケーションの作り方」という本のP135にサンプルが出ています。以下に該当する部分を引用します。

    // 基本となるSQL
    $sql = 'SELECT id, title, author, publisher, date, price FROM books';
    if ($title !== '') { // 検索条件titleの追加(LIKE)
      $conditions[] = "title LIKE ? ESCAPE '#'";
      $ph_type[] = 'text';
      $ph_value[] = escape_wildcard($title);
    }
    if ($price !== '') { // 検索条件priceの追加(大小比較)
      $conditions[] = "price <= ?";
      $ph_type[] = 'integer';
      $ph_value[] = $price;
    }
    if (count($conditions) > 0) { // WHERE句がある場合
      $sql .= ' WHERE ' . implode(' AND ', $conditions);
    }
    $stmt = $mdb2->prepare($sql, $ph_type); // SQL文の準備
    $rs = $stmt->execute($ph_value); // バインド・問い合わせ実行

ご覧のように、WHERE句の断片を配列に追加していき、同時に型と値も別の配列に追加しているだけです。
面倒なように見えるかもしれませんが、単純な繰り返しなので、難しくはないと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/10 15:37

    te2jiさま

    ご親切なアドバイスをありがとうございます。
    お返事までお時間を頂きましたが、動的な検索条件等、応用的なアドバイス、とても参考になりました。ありがとうございました!

    キャンセル

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

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

関連した質問

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

  • PHP

    20343questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    5854questions

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