テーブルから複数のレコードにマッチする条件

このQ&Aのポイント
  • 複数のレコードにマッチする条件をテーブルから取得する方法について
  • SQL文を使用してテーブルから複数のレコードにマッチする条件を取得する方法について
  • テーブルから複数のレコードにマッチする条件を検索する方法について
回答を見る
  • ベストアンサー

テーブルから複数のレコードにマッチする条件

以下のようなSQL文があった場合 SELECT table_a.* FROM table_a LEFT JOIN table_b ON (table_a.id = table_b.aid) これでtable_bを連結したtable_aができると思いますが、table_bのフィールドは id , aid, value となっていた場合、valueが「1」かつ「2」のデータを検索する場合は、どのようにWHERE句を書けばいいのでしょうか。 WHERE (table_b.value = '1' AND table_b.value = '2') ではうまく取得出来ませんでした。 お分かりの方、よろしくお願いします。

  • MySQL
  • 回答数2
  • ありがとう数16

質問者が選んだベストアンサー

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

>valueが「1」かつ「2」のデータを検索する この命題では日本語としてなりたたない なんとなく言いたいことはわかるのだけど条件提示が杜撰すぎ 以下のどれかだと推測します (1)valueが1および2を含むデータをすべて抽出 →仮に別途value=3のデータがあたったらそれも抽出 (2)valueが1および2を含むデータの内、1,2に該当するデータのみ抽出 →仮に別途value=3のデータがあってもむし (3)valueが1および2しかないデータを抽出 →仮に別途value=3のデータがあったら1,2に合致しても抽出しない たぶん(2)なんだろうなぁということで以下 //元データ create table table_a (id int,data varchar(20)); insert into table_a values(1,'a1'),(2,'a2'),(3,'a3'); create table table_b (id int,aid int,value int); insert into table_b values(1,1,1),(2,1,2),(3,1,3),(4,2,1),(5,2,2),(6,3,1),(6,3,3); //単純な表示 SELECT * FROM table_a WHERE table_a.id in (SELECT aid FROM table_b where value in (1,2) group by aid having count(distinct value)=2 ) //table_bの情報も含めた表示 SELECT * FROM table_a INNER JOIN table_b ON table_a.id = table_b.aid and value in (1,2) WHERE table_a.id in (SELECT aid FROM table_b where value in (1,2) group by aid having count(distinct value)=2 )

ok-rjak
質問者

お礼

杜撰な説明にも関わらず意図をくみ取っていただき有難うございます。 まさしく仰るとおり(2)で、しかも単純な表示の方でOKです。 やりたいことはぼんやりわかるのですが、それをSQLで表現するのが、自分はまだまだ未熟だと実感します。 こうして提示していただき、ひとつひとつかみ砕いて理解していき、最終的に思うとおりの結果に繋がりました。 本当に有難うございました!

その他の回答 (1)

  • Picosoft
  • ベストアンサー率70% (274/391)
回答No.1

> valueが「1」かつ「2」のデータを検索する場合は、どのようにWHERE句を書けばいいのでしょうか。 これでは車屋さんに行って、「ATかつMTの車を探してください」と言っているのと同じです。 valueには1つの値しか入りませんので、「valueが1かつ2」という状態はあり得ません。 検索条件を一度よく整理してみてください。

ok-rjak
質問者

補足

少し説明が足りなかったようです。申し訳ありません。 table_bにaidが同一で、valueが違うデータが複数件挿入されています。 aidが同一で、valueが「1」と「2」のレコードを持つデータの情報をtable_aから抜き出したいということなのです。

関連するQ&A

  • サブクエリを利用したSQL文から複数の抽出条件

    例えば、以下のようなサブクエリを利用したSQL文があります。 SELECT table_a.* FROM table_a LEFT JOIN (SELECT table_b.* FROM table_b LEFT JOIN table_c ON (table_b.id = table_c.bid) WHERE table_b.type='1') AS tbl ON (table_a.id = tbl.aid) このSQL文にWHERE句で条件を指定したいのですが、サブクエリで指定しているtblテーブルのvalueフィールドが「1」と「20」のものを抽出したいと思います。 WHERE (tbl.value='1' AND tbl.value='20') としても結果が帰って来ません。 これは、WHEREする条件の数だけ、サブクエリでテーブルを作って条件を指定するのでしょうか? 効率が悪そうなので、他の方法があるのではと思いご質問させて頂きました。 お分かりになる方がいれば、よろしくお願いします。

  • テーブル結合で、結合フィールドをWHERE句に用いた時に、結合フィールドのデータがNULLになってしまう。

    MySQL 4.0.24-standard + PHP Version 4.3.11 を使用しています。 下記のような table_a, table_b があり、idフィールドで外部結合させています。 table_a id|value ------- 1 | 0 2 | 1 table_b id|name ------- 1 | A 2 | B SELECT * FROM table_a NATURAL LEFT OUTER JOIN table_b; result id|value|name -------------- 1 | 0 | A 2 | 1 | B しかし、下記のクエリでは、このようにidがNULLになってしまいます。 SELECT * FROM table_a NATURAL LEFT OUTER JOIN table_b WHERE table_a.id = 1; result id |value|name -------------- NULL| 0 | A 以下のような結果を得たいのですが、どうすれば良いのでしょうか? result id|value|name -------------- 1 | 0 | A

    • ベストアンサー
    • MySQL
  • joinの場合のテーブル名の別名の使用方法

    select * from table1 a,table2 b where a.field1=b.field1; とできますが select * from table1 as a left join table2 as b on a.field1=b.field1; とできません。 joinの場合にテーブル名の別名を使う方法を教えてください

  • テーブルの結合について

    以下の二つを実行すると、2 の方がかなり速いのですが理由が分かりません。 分かる方教えてもらっていいですか? DBはMYSQLでInoDBです。 ちなみに Aは1万件、B は10万件ほど 1 のSQL SELECT * FROM A LEFT JOIN (SELECT * FROM B WHERE ・・・ GROUP BY XXX) B ON A.id = B.XXX WHERE ・・・ GROUP BY A.id 2 のSQL (SELECT * FROM A ・・・ GROUP BY ID ) A LEFT JOIN (SELECT * FROM B WHERE ・・・ GROUP BY XXX) ON A.ID = B.XXX.ID

  • 紐付いている3つのテーブルに対しての検索条件の指定がうまくいきません・・。

    紐付いている3つのテーブルに対しての検索条件の指定がうまく書けません。 3つのテーブルが紐付いています。 ・main_tableのIDと、note_id_tableのID ・note_id_tableのnote_IDと、note_value_tableのnote_ID main_table ID, name ----------- 1, aaa 2, bbb 3, ccc 4, ddd 5, eee note_id_table ID, note_ID ----------- 1, 1 1, 2 1, 3 1, 4 3, 5 3, 6 4, 7 4, 8 4, 9 5, 10 note_value_table note_ID, note_value ----------- 1, AAAA1 2, BBBB1 3, CCCC1 4, DDDD1 5, AAAA3 6, EEEE3 7, FFFF4 8, GGGG4 9, HHHH4 10, IIII5 検索の対象にしたいのは、note_valueです。 今まで、「note_valueに検索文字列が含まれている」main_tableのレコードを取得していました。 SELECT main_table.* FROM main_table LEFT JOIN note_id_table ON main_table.id = note_id_table.id LEFT JOIN note_value_table ON note_id_table.note_ID = note_value_table.note_ID WHERE note_value_table.note_value LIKE '%AAA%' 上記クエリだと、note_valueにAAAを含んでいるnote_ID:1,5を持つ、 main_tableのID:1,3のレコード、2件が返ってきます。 これを、検索文字列のNOT検索とAND検索に対応させたいのです。 NOT検索について、 WHERE NOT(note_value_table LIKE '%AAA%') としてみたのですが、main_tableのID:1,3,4,5のレコードが返ってきました。 期待した動作は、main_tableのID:2,4,5でした。 まず、note_value_tableにデータを持っていないmain_table.id:2はNULLのようで、 この条件では無視されてしまうようです。 また、main_table.id:1,3が返ってきてしまうのは、 main_table.id:1に紐付いているnote_IDの内、2,3,4と main_table.id:3に紐付いているnote_IDの内、6に条件が引っかかってしまうようなのです。 AND検索ですが、上記クエリの条件を WHERE note_value_table LIKE '%AAA%' AND note_value_table LIKE '%BBB%' としたところ、0件となってしまいました。 期待した動作は、note_valueにAAAとBBBを含んでいるnote_ID:1を持つ、 main_tableのID:1のレコード、この1件が返ってくることでした。 どうもこの条件だと、一つのnote_valueにAAAとBBBが含まれていないとHITしないようです。 結局JOINしているので、note_valueの数だけ同じmain_tableが前にくっついてるイメージなんですよね。 main_tableのレコード末端に、紐付いているnote_valueのフィールドを横に繋げるか、 紐付いているnote_valueの文字列を連結したものを一つのフィールドとして解釈するようなことができれば 実現できるのかなぁと思いました。 試行錯誤の末に、パフォーマンスが非常に悪いんですが、下記クエリで機能的には実現できたのですが、 これでは使えないので何かいいアイディアなどあればご教授お願いしたいです。 サブクエリを使いたくないというのがあります。 --AAAの検索 JOINする時に検索してしまうようにしてみました。 また、そのためには、note_id_tableからnote_IDを取得できていないとだめなので、 サブクエリ化してみました。 SELECT main_table.* FROM main_table LEFT JOIN note_value_table ON note_value_table.note_ID IN (SELECT note_ID FROM note_id_table WHERE main_table.id = note_id_table.id) AND note_value_table LIKE '%AAA%' WHERE note_value_table.note_value IS NOT NULL --AAAのNOT検索 WHERE条件を逆にするだけにしました。 --AAAとBBBの検索 検索条件1つに対して、JOINを増やしていくようにしました。 JOINが増えるのもそうですが、サブクエリも倍になってしまい、 検索条件を増やせば増やすほどパフォーマンスが落ちてしまいます。。 SELECT main_table.* FROM main_table LEFT JOIN note_value_table AS note_value_table1 ON note_value_table1.note_ID IN (SELECT note_ID FROM note_id_table WHERE main_table.id = note_id_table.id) AND note_value_table1 LIKE '%AAA%' LEFT JOIN note_value_table AS note_value_table2 ON note_value_table2.note_ID IN (SELECT note_ID FROM note_id_table WHERE main_table.id = note_id_table.id) AND note_value_table2 LIKE '%AAA%' WHERE note_value_table1.note_value IS NOT NULL AND note_value_table2.note_value IS NOT NULL

    • ベストアンサー
    • MySQL
  • 同じ値が存在しないレコードの抽出方法について

    下記のテーブルの中で、 b_tableテーブルのidフィールドの値が1つしかない(重複していない)フィールドを抽出したいと思います(この場合ですが、3002と3004を抽出したいです)。 その際、抽出条件を下記の【※※※ここに記述を追加※※※】に記述することで実現したいと思ったのですが、その場合どのようなsql文を書けば良いか分かりませんでした。 その為、このような場合、どのようなsql文を書けば良いかご存知の方がいらっしゃいましたら、ご教示の程、よろしくお願いします。 なお、【※※※ここに記述を追加※※※】に記述を追加したい理由ですが、既存のSQL文にこの条件を追加したいのですが、WHERE以前は別の部分に記述されており、その部分が変更できない為です。 なお、下記のWHERE以前の記述はあくまでサンプルであり、重複していないフィールドを抽出するSQL文と直接関係のない記述でしたら、変更していただいても大丈夫かもしれません(この点曖昧で申し訳ございません。移植元の記述ではテーブルを連結しているように見受けられたため、連結の仕方が多少変わる分には問題ないのかなと思っています。この点については実際にソースをご提示いただければ、それを元に移植させていただいた上で、ご回答差し上げたいと思います)。 ■SQL文 SELECT a.id FROM `a_table` AS a LEFT JOIN `b_table` AS b ON a.id = b.id WHERE 【※※※ここに記述を追加※※※】 ■a_tableテーブル CREATE TABLE IF NOT EXISTS `a_table` ( `auto_id` int(3) NOT NULL, `id` varchar(4) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; INSERT INTO `a_table` (`auto_id`, `id`) VALUES (101, '3001'), (102, '3002'), (103, '3003'), (104, '3004'); ■b_tableテーブル CREATE TABLE IF NOT EXISTS `b_table` ( `auto_id` int(3) NOT NULL, `id` varchar(4) NOT NULL, `no` varchar(1) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; INSERT INTO `b_table` (`auto_id`, `id`, `no`) VALUES (101, '3001', '1'), (102, '3001', '2'), (103, '3001', '3'), (104, '3002', '2'), (105, '3003', '1'), (106, '3003', '2'), (107, '3004', '1'); 以上、よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 1テーブル&複数レコードの更新に対して1度のupdate文での処理方法

    1テーブル&複数レコードの更新に対して1度のupdate文での処理方法 Delphi2010+SQL SERVER 2005で開発しています。 update文で、 現在下のようにwhileで複数レコードに対して、 1回、1回、sqlを発行して、更新しています。 これを、一度のSQLの発行で処理できないものでしょうか? 更新テーブルは1つで、更新する項目も同じです。 更新するデータと、where句の条件が異なります。 もし可能なようでしたら、どうかご教授お願いします。 update table set A=1,B=2 where id=1 update table set A=2,B=3 where id=5 update table set A=9,B=99 where id=7 update table set A=5,B=10 where id=15 update table set A=1,B=10 where id=75

  • 再投稿:フィールドの値をテーブル名&フィールド名にして参照したい

    すみません。若干記入ミスだったので再投稿します。 こちらにご解答お願いします。 TABLE_a ・Ta_id ・key_table ・key_field ・key_no TABLE_b ・Tb_id ・Tb_name TABLE_c ・Tc_id ・Tc_name と3つのテーブルがあり、 key_tableに「TABLE_b」、key_fieldに「Tb_id」が入ってて、 TABLE_aとTABLE_bを select の left join して抽出したい場合、 どういうSQL文になるのでしょうか。 select * from TABLE_a left join case key_table when 'TABLE_b' then 'TABLE_b' when 'TABLE_c' then 'TABLE_c' end on 'TABLE_a.key_field'.key_no = case key_table when 'TABLE_b' then ''TABLE_a.key_table'.Tb_id' when 'TABLE_c' then ''TABLE_a.key_table'.Tc_id' end ; とやってみたのですが、うまくできませんでした。 ご教示お願いします。

  • ある条件を含まないというクエリがうまく書けません。

    ある条件を含まないというクエリがうまく書けません。 test_table ID,name ----------- 1,aaa 2,bbb 3,ccc 4,ddd 5,eee test_table2 ID,value ----------- 1,100 1,200 1,300 1,400 2,100 2,200 3,900 3,800 4,400 4,500 4,600 5,100 今まで下記クエリのように、test_tableのIDとtest_table2のIDでジョインして、 test_table2のvalueに"200"を含んでいるtest_tableのレコードを取得していました。 SELECT DISTINCT test_table.* LEFT JOIN test_table2 ON test_table.ID = test_table2.ID WHERE test_table2.value = 200; (test_tableのID:1と2のレコードが返ってきます。) これを、test_table2のvalueに"200"を含まないものを返すようにしたいのです。 (test_tableのID:3と4と5のレコードを返したい) 下記クエリを作ってみましたが、ID:1と2も返ってきてしまいます。 ID:1のvalueの"100","300","400"、ID:2のvalueの"100"に条件が合ってしまうようです。。 SELECT DISTINCT test_table.* LEFT JOIN test_table2 ON test_table.ID = test_table2.ID WHERE test_table2.value != 200; なにが良い方法があればご教授下さい。

    • ベストアンサー
    • MySQL
  • テーブル結合の条件指定について

    以下のようなテーブルが3つある場合に2つのテーブルにあるポイントを合計して取得したいと思っています。 ただ、外部結合しているtable_cに条件を与えるとうまく取得できません。 table_cにcdがある場合は条件を指定し、 ない場合は条件を指定しないようにするにはどうすればいいのでしょうか。 【table_a】 id    name ------------------ a1    aaa a2    bbb a3    ccc 【table_b】 b_id     a_id   user_id    point --------------------------------- b1     a1    00001    5 b2     a1    00002    2 b3     a3    00007    10 b4     a2    00356    10 【table_c】 c_id    user_id    cd     bonus_point ------------------------------------------------ c1     00001    cd_1    1 c2     00007    cd_2    1 c3     00356    cd_1    1 SELECT table_b.user_id as user_id , (ifnull(table_b.age_count) + ifnull(table_c.bonus_point, 0)) as total_point FROM table_a INNER JOIN table_b ON (table_b.a_id=table_a.a_id)    LEFT JOIN table_c ON (table_c.user_id=table_b.user_id) WHERE table_c.cd = 'cd_1' ORDER BY total_point desc ■結果 user_id    total_point ----------------------------- 00356     11 00001      6 ■求めたい結果 user_id    total_point ----------------------------- 00356     11 00001      6 00002     2 よろしくお願いします。

    • ベストアンサー
    • MySQL