• ベストアンサー

SQL文の抽出がうまくいきません。ご指導お願いいたします。

写真を添付していない投稿も表示させたいのです。 今のSELECT文だと写真添付されているものだけ抽出されます。 tokou_table(略t) ┌───┬────┬────┐ |tku_id|cont_id |post_id | ├───┼────┼────┤ |001  | 5   |21   | ├───┼────┼────┤ |002  | 4   |22   | └───┴────┴────┘ post_table(略p) ┌───┬────┬────┐ |pst_id|cont_id |atch_id | ├───┼────┼────┤ |21 | 5 |0    | ├───┼────┼────┤ |22 | 4 |1 | └───┴────┴────┘ post_text_table(略pt) ┌───┬────┬────┐ |pst_id|pst_sub |pst_txt | ├───┼────┼────┤ |21 | 実験 |テキスト| ├───┼────┼────┤ |22 |サンプル|書込み | └───┴────┴────┘ atch_table(略at) ┌───┬────┐ |pst_id|atch_id | ├───┼────┤ |21 | 51 | └───┴────┘ atch_dat_table(略ad) ┌────┬────┐ |atch_id |pht_dat | ├────┼────┤ |51 |a.jpg | └────┴────┘ $sql = "SELECT t.tku_id, t.cont_id, p.forum_id, p.pst_id, pt.pst_id, pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat FROM " . TOKOU_TABLE . " AS t, " . POST_TABLE . " AS p, " . POST_TEXT_TABLE . " AS pt," . ATCH_TABLE . " AS at, " . ATCH_DAT_TABLE . " AS ad WHERE t.cont_id = 4 AND t.cont_id = p.cont_id AND p.pst_id = t.post_id AND p.pst_id = pt.pst_id AND pt.pst_id = at.pst_id AND at.atch_id = ad.atch_id

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

  • ベストアンサー
回答No.5

#4回答者です。 対応するデータがなくても結果を得るには、OUTER JOINを使用する場合が多いですが、サポートバージョンが、マニュアルを見た範囲では「4.0.11以降」なのかも知れません。 既に「5.0」も正式リリースされていますが、バージョンアップは可能でしょうか? ■SQL記述例 略t→略p→~→略adの階層順に、子供に相手がいなくても、NULL値で結合する例です。 バージョン5.0で実機確認済みですが、あなたの希望通りかどうか分からないので確認してみてください。 SELECT t.tku_id, t.cont_id, p.forum_id, p.pst_id, pt.pst_id, pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat FROM TOKOU_TABLE AS t LEFT OUTER JOIN POST_TABLE AS p ON t.cont_id = p.cont_id AND p.pst_id = t.post_id LEFT OUTER JOIN POST_TEXT_TABLE AS pt ON p.pst_id = pt.pst_id LEFT OUTER JOIN ATCH_TABLE AS at ON pt.pst_id = at.pst_id LEFT OUTER JOIN ATCH_DAT_TABLE AS ad ON at.atch_id = ad.atch_id WHERE t.cont_id = 4 ;

参考URL:
http://dev.mysql.com/doc/refman/4.1/ja/join.html
wow_chan
質問者

お礼

的確なご指導ありがとうございます。 LEFT OUTER JOINでもできました。すばらしい、さすがですね。 本当に感謝いたします。 JOINでもWHEREが使用できるのは知らなかったです。 みなさまのご指摘によりテーブルを4つにしてみてLEFT JOINでもできました。 一応下記になりました。 $sql = "SELECT t.tku_id, t.cont_id, pt.pst_id, pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat FROM " . TOKOU_TABLE . " AS t LEFT JOIN " . POST_TEXT_TABLE . " pt ON pt.post_id = t.post_id LEFT JOIN " . ATCH_TABLE . " at ON at.pst_id = pt.pst_id LEFT JOIN " . ATCH_DAT_TABLE . " ad ON at.atch_id = ad.atch_id WHERE t.cont_id = 4 ORDER BY t.con_id DESC "; 添付していない投稿の表示されない画像は透明なGIFで対応しました。 まだ改善の余地はありそうです。 ご指導ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

回答No.4

5階層になっているようですが、対応するデータの有無により、対応付けの要否が分かりません。 MySQLの質問をする場合は、バージョンも書いてくださいね。 せっかくSQL例を提示しても、バージョンによる実行可否がありますから。

wow_chan
質問者

補足

そうですよね。大変失礼しました。 MySQLは4.0.0-alphaです。 phpによる記述になります。 phpは4.2.3です。 ご指摘ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

これはPHPで処理しているのでしょうか? そもそもFROM節のつなぎ方に文法的な問題がありそうです。 このままではまともに動かないと思いますけど。 本題: ファイルのアタッチがあるものとないものがあり 両方表示したいのですよね? そういう場合はadテーブルでatch_id=0でNULLを作っておき atテーブルでアタッチがないものを0指定すればよいのでは? (0じゃなくても特徴的な番号999とかでもいいです) 後はうけとった側でNULLを例外処理すればすむので。

wow_chan
質問者

補足

回答ありがとうございます。 大変参考になるご意見ありがとうございます。 ただ、atテーブルのレコードが増えていくという形になるので なるべくならatテーブルのレコードは添付しているものだけの レコードにしたいのです。 でも、できなければご指導いただいたようにするしかないのかな と思っています。 JOIN を使って今やっていますが。。。難しいです。 JOINを使うやり方でいい構文がありましたらご指導ください。

全文を見る
すると、全ての回答が全文表示されます。
  • moon_night
  • ベストアンサー率32% (598/1831)
回答No.2

どのような仕様かはわかりませんが、テーブルを分けすぎだと思います。 それはさておき、whereで全てのテーブルがないと連結できないので対象からはずれてしまいます。 その場合は、あるかないかが分からないものに関しては left joinで連結してみてください。 データがなくてもNULLが入るはずです。

wow_chan
質問者

お礼

回答ありがとうございます。 テーブルは訳あって分けています。 ご指摘の通り、ひとつに出来れば簡単な話なんですが、すみません。 left joinでやってみます。わからなければ再度質問させてください。

全文を見る
すると、全ての回答が全文表示されます。
  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

テーブルが細分化されていますがまとめたらだめなんでしょうか。 idの役割が不明なのでわかりませんが全部のテーブルを1つにまとめられそうな気がします。 目的があって分けてあるのでしたらすみません。

wow_chan
質問者

お礼

回答ありがとうございます。 ご指摘の通り、テーブルをひとつにできれば簡単なんですけど。 サーバレスポンスと写真の添付の関係でこういう仕様になっています。 投稿に写真添付が何枚も投稿できるようにと。。。 そこがエーラーの原因なのですが、なんとかがんばって作ってみたいと思います。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • SQL文の重複の削除でうまくいきません。

    昨日は回答いただきありがとうございました。 恐縮ですが、また質問させていただきます。 ひとつの投稿に対して2つの添付ファイルがある場合post_tableのtku_idが重複しているのですが、それに対してpost_idの小さい方を表示させたいのです。 post_tableのデータはpst_idで22と23がtku_idが同じで、22の方を表示させたいのです。 GROUP BY HAVING や自己リレーpost_table p2などやってみましたがダメでした。 どういうSQL文にするのがベストなんでしょうか? 未熟ものですが、ご指導いただけると助かります。 宜しくお願いいたします。 $sql = "SELECT t.tku_id, t.cont_id, p.pst_id, p.tku_id, pt.pst_id, pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat FROM " . TOKOU_TABLE . " AS t LEFT JOIN " . POST_TABLE . " p ON t.cont_id = p.cont_id LEFT JOIN " . POST_TEXT_TABLE . " pt ON p.pst_id = pt.pst_id LEFT JOIN " . ATCH_TABLE . " at ON at.pst_id = pt.pst_id LEFT JOIN " . ATCH_DAT_TABLE . " ad ON at.atch_id = ad.atch_id WHERE t.cont_id = 4 GROUP BY p.tku_id ORDER BY t.cont_id DESC "; tokou_table(略t)  tku_id cont_id  post_id     001   5    21   002   4    22 post_table(略p)  pst_id cont_id atch_id tku_id    21   5     0   001   22   4     1   002   23   4     1   002 post_text_table(略pt)  pst_id pst_sub pst_txt   21    実験  テキスト  22   サンプル 書込み atch_table(略at)  pst_id atch_id   21   51   23   52 atch_dat_table(略ad)  atch_id pht_dat    51   a.jpg   52   b.jpg MySQLは4.0.0-alph php4.2.3による記述です。

    • ベストアンサー
    • MySQL
  • PL/SQLのDELETE文について

    PL/SQLでDELETE文を書こうとしているのですが、 文法がわかりません。。。 分かる方がおられましたら、教えてくださいm(_ _)m 今、TABLE1を削除したいのですが、条件がいろいろあって、 以下のように書いてみたのですがダメでした。 こういう書き方は、できないんでしょうか・・・。 削除条件は、TABLE2に存在し、かつ、TABLE2のTENSUが0のもので、 TABLE3が存在しないものです。 DELETE TABLE1 FROM TABLE1 ,TABLE2 ,TABLE3 WHERE TABLE1.ID = TABLE2.ID AND TABLE2.TENSU = 0 AND Not Exists (SELECT TABLE3.ID FROM TABLE3 WHERE TABLE3.ID = TABLE2.ID) 説明が下手なので、うまく、伝わっているか、心配なのですが・・・、 よろしくお願いします。

  • このSQL文の意味を教えてください。

    SQL勉強中の者です。このSQL文の意味を教えてください。 SELECT A.* FROM table AS A, table AS B WHERE A.id *= B.id AND A.flag = 1 tableにAとBという別名をつけて、Aの全ての項目を抽出しているというところまでは分かりました。 分からないのは「WHERE A.id *= B.id」の部分です。ただの「=」なら分かりますが「*=」って何ですか? あと、AとBのテーブルが同じなのですが、同じテーブルを2つ並べている意味がよく分かりません。 よろしくお願いします。

  • サブクエリを利用した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する条件の数だけ、サブクエリでテーブルを作って条件を指定するのでしょうか? 効率が悪そうなので、他の方法があるのではと思いご質問させて頂きました。 お分かりになる方がいれば、よろしくお願いします。

  • SQLで・・

    すみません、教えてください。 次のようなデータがあります。 table_A Name1 Name2 ----------- 1   2 3   4 table_B ID    Name --------------- 1     あ 2     い 3     う 4     え 次のような検索結果が欲しいとします。 Name1 Name2 ------------- あ    い う    え この結果を導くSELECT文はどう書けばいいでしょうか? 今、 select B.Name as Name1, C.Name as Name2 from table_A A, table_B B, table_B C where A.Name1=B.ID AND A.Name2=C.ID とやってみましたが、検索結果は0件になってしまいます。 お知恵をお貸しください!

  • SQLで重複値を除去したものを抽出したい

    SQLで重複を除去したいのですが、DISTINCTやGROUP BYも検討したのですが、どうしても良い方法が見つからなかったので質問させて頂きます。 テーブルの構成は以下のようになっています。 roomsテーブル id(INTEGER) public(BOOLEAN) updated_at(DATETIME) created_at(DATETIME) messagesテーブル id(INTEGER) sendfrom_list_id(INTEGER) sendto_list_id(INTEGER) room_id(INTEGER)※roomsテーブルへの外部キー body(STRING) updated_at(DATETIME) created_at(DATETIME) 更に条件は以下のようになっています。 ・アウトプットとして得たいのは rooms.updated_at rooms.id rooms.public messages.room_id messages.sendfrom_list_id messages.sendto_list_id messagess.body の7カラム。 ・rooms.publicがTRUEである ・messages.room_id = rooms.idであること ・updated_atでDESCにソート このような条件を満たすSQL文は以下のように書くことができました。 SELECT R.updated_at, R.id, R.public, M.room_id, M.sendfrom_list_id, M.sendto_list_id, M.body FROM messages AS M, rooms AS R WHERE R.public = "t" AND M.room_id = R.id ORDER BY R.updated_at DESC; しかし、ここに更に「rooms.idが重複しないもののみ抽出」という条件を加えたいのですが、どうしてもうまく行きません。 DISTINCTでは複数の中から一部のカラムだけをDISTINCTすることはできないようですし、GROUP BYも考えましたがどうやれば良いかわかりませんでした。 どなたか良い方法を教えて下さい。

  • SQL文 テーブルの作成方法について

    以下のようなTABLE1からTABLE2というテーブルを作成したいと考えております。 元テーブル(TABLE1)は、IDという項目がキーとなってデータが入っており、NAME1とNAME2という項目があります。 (NAME1は必ず値が入っていますが、NAME2は値が入っていない場合もあります) 加工後のテーブル(TABLE2)で、NAME1とNAME2の値を結合した形で結果を出力したいと考えております。 (新たに作成したNAMEカラムは、必ずしもユニークになっているとは限りません。NAMEとIDを組み合わせるとユニークになります) ---------------------------------------------------- ■ TABLE1 ID NAME1 NAME1_CATE NAME2 NAME2_CATE ---------------------------------------------------- 001 鈴木 A 山田 B 002 山本 A 003 佐藤 A 高橋 B ---------------------------------------------------- ---------------------------------------------------- ■ TABLE2 ID NAME NAME_CATE ---------------------------------------------------- 001 鈴木 A 001 山田 B 002 山本 A 003 佐藤 A 003 高橋 B ・・・ ---------------------------------------------------- いろいろ試していますが、どのようなSQL文を書いたらよいのか分かりません。 現状のSQL(エラーとなります) ====================================================================================== SELECT ID, NAME, NAME_CATE FROM (SELECT ID, NAME1 as NAME, NAME1_CATE as NAME_CATE FROM TABLE1 WHERE NAME1<>NULL) JOIN (SELECT ID, NAME2 as NAME, NAME2_CATE as NAME_CATE FROM TABLE1 WHERE NAME2<>NULL) ====================================================================================== 初歩的な質問になるかと思ってしまうかと思いますが、よろしくお願いいたします。

  • SQL文で作ったデータを使ったUPDATE

    環境はMySQL5.6です。 下記のテーブルccがあります。 【cc】 shisan  user 500  tanaka 1000  mikami 400   tanaka 1300  mikami SELECT Total, user FROM (SELECT SUM( cc.shisan ) AS Total, user FROM cc GROUP BY user) AS t1 とすることによりSQL上にt1テーブルを作ることが出来ます。 【t1】 Total  user 900  tanaka 2300  mikami 次に、このt1テーブルのTotalの数値を下記のmoney_tableにあるcash欄に挿入(UPDATE)したいと考えています。 【money_table】 cash  user 0   tanaka 0   mikami そこで下記のSQL文を作ったのですがエラーになります。 UPDATE money_table,cc SET money_table.cash=t1.Total FROM (SELECT Total, user FROM (SELECT SUM( cc.shisan ) AS Total, user FROM cc GROUP BY user) AS t1) WHERE money_table.user=t1.user どこがいけないのかご指導いただけませんでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • SQLで他のテーブルに無いIDの抽出

    MySQLを使っています。 下記は、 1.テーブルaaaには、存在するidのものが、 2.テーブルbbbには、存在しない、 3.テーブルaaaのレコードを抽出したいものです。 "SELECT DISTINCT aaa.*" + " FROM aaa" + " WHERE (aaa.flag = false)" + " AND NOT EXISTS (SELECT * FROM bbb" + " WHERE (aaa.id = bbb.id) AND (bbb.flag = false))" ですが、実行すると、下記エラーがでます。 SQLException:Base table or view not found, message from server: \"Unknown table 'bbb' in where clause" どうすればよいのでしょうか?

    • ベストアンサー
    • MySQL
  • ASPでmdbファイルからデータの抽出(SQL)

    ASPでmdbファイルからデータを抽出したいのですが、うまくいきません。 TABLE1に以下のレコードがあるとします(MS-ACCESS) ID,RANK1,RANK2(TABLE1) 1,1,1 2,1,2 3,1,3 4,2,1 5,2,2 6,2,3 RANK1、RANK2は以下のテーブルを参照し RANK,RANK_NAME(TABLE2) 1,上 2,中 2,下 このように表示させたいのです。 1,上,上 2,上,中 3,上,下 4,中,上 5,中,中 6,中,下 しかし、ACCESSのクエリーでは動作するのですが、ASPでは上中下が表示されません。 以下ASPで記述したSQL文です SELECT TABLE1.ID, RANK1.RANK_NAME, RANK2.RANK_NAME FROM (TABLE1 INNER JOIN TABLE2 AS RANK1 ON TABLE1.RANK1 = RANK1.RANK) INNER JOIN TABLE2 AS RANK2 ON TABLE1.RANK2 = RANK2.RANK; 何か悪いのでしょうか? 宜しくお願いいたします。