みんなの「教えて(疑問・質問)」にみんなで「答える」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による記述です。

投稿日時 - 2006-03-03 11:51:42

QNo.2003846

困ってます

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

#1です。
SQL文のみですが、下記みたいになるかと思います。
---
SELECT q.*, pt.*, at.*, ad.*
FROM (((
SELECT t.tku_id, t.cont_id, p.forum_id, Min(p.pst_id) AS pst_id_m
FROM tokou_table t LEFT JOIN post_table p ON t.cont_id = p.cont_id
GROUP BY t.tku_id, t.cont_id, p.forum_id
HAVING (t.cont_id)="4"
) q LEFT JOIN post_text_table pt ON q.pst_id_m = pt.pst_id
) LEFT JOIN atch_table at ON pt.pst_id = at.pst_id
) left join atch_dat_table ad ON ad.atch_id = at.atch_id;

投稿日時 - 2006-03-06 08:53:24

補足

SQL文ありがとうございます。
いろいろやってみてますが、エラーになってしまいます。
Verの問題かもしれないので、自力でやっています。

q となっているのは p の間違いではないですよね?
丁寧にご回答いただきありがとうございます。

投稿日時 - 2006-03-06 11:47:58

このQ&Aは役に立ちましたか?

3人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

#1です。
SELECT t.tku_id, t.cont_id, p.forum_id, Min(p.pst_id) AS pst_id_m
FROM tokou_table t LEFT JOIN post_table p ON t.cont_id = p.cont_id
GROUP BY t.tku_id, t.cont_id, p.forum_id
HAVING (t.cont_id)="4"
の部分を別名でqとしています。
---
MySQLは昔使ったことがあるのですが、
あまり仕様を覚えていないので。。。。。

投稿日時 - 2006-03-06 12:20:38

お礼

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

まだ試行錯誤しながらやってみてます。

また機会がありましたら宜しくお願いします。

投稿日時 - 2006-03-20 09:09:42

ANo.4

#2の補足です。バージョン次第ですがMySQL使いとしては
サブクエリーは使わないものとして・・・。
SELECT min(pst_id) as pst_id,cont_id,atch_id,tku_id from p group by tku_id;
とするとtku_idをユニークなテーブルが表示されます。
このデータをテンポラリーに流し込んで、pの変わりに
使えば、うまくいくと思います。

CREATE TEMPORARY TABLE temp_p SELECT min(pst_id) as pst_id,cont_id,atch_id,tku_id from p group by tku_id;
SELECT t.tku_id, t.cont_id, temp_p.pst_id,pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat
FROM t
LEFT JOIN temp_p ON t.cont_id = temp_p.cont_id
LEFT JOIN pt ON temp_p.pst_id = pt.pst_id
LEFT JOIN at ON at.pst_id = pt.pst_id
LEFT JOIN ad ON at.atch_id = ad.atch_id
WHERE t.cont_id = 4

投稿日時 - 2006-03-06 10:54:47

補足

お忙しい中、ご回答ありがとうございます。
いろいろ作戦があるんですね。関心してしまいます。
o_chi_chiさんとyambejpさんどちらも検証しています。

Mysqlのエラーなのか構文が間違っているのか、エラーになるので
調べています。
必ずお返事いたしますので、しばらくお待ちください。

回答本当にありがとうございます。感謝です。

投稿日時 - 2006-03-06 13:43:19

お礼

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

まだ試行錯誤しながらやってみてます。

また機会がありましたら宜しくお願いします。

投稿日時 - 2006-03-20 09:10:00

ANo.2

添付されるファイルの上限値が少数できまっている
たとえばどんなに多くても5個とか・・・
であれば、予めフィールドを5個つくっておくと
効率的です。添付データが1つしかなくても、
残りのフィールドには0とかNULLを入れておけばいいの
ですから。(その辺は前回もお答えしましたので割愛)

上限値が決まっていないもしくは上限値があるが
数量が多い、たとえば100とか・・・の場合は、
結果は行で別れている方が後処理しやすいでしょうね。

そもそもが戻ってきた結果をどう表現したいのかも
提示されていないので、なんとも答えようがありません。
SQLは所詮データの塊でしかないので、全ては結果を
表示したり保存したりする仕様次第でしょう。

投稿日時 - 2006-03-03 18:02:41

補足

回答ありがとうございます。
ご指摘の通りフィールドをあらかじめ作る方が楽なんですけど。。。
SQLもそのほうが簡単ですよね。

でも今回はこれでいきたいと思います。
結果を説明させていただくと、投稿したデータに写真が掲載されるという仕組みです。
投稿する写真は何枚でも掲載できるようにしています。
プログラムで表示させたいのは一覧で表示する際に写真をひとつだけ表示したいのです。
投稿に写真を追加して2枚になっても表示は一番最初に投稿した写真が表示したいのです。
現状のSQLだと最後に投稿したものが表示されるようになっています。

投稿するとt、p、ptにそれぞれレコードが追加されます。
写真を添付するとat、adにレコードが追加されます。

投稿日時 - 2006-03-03 18:08:43

ANo.1

SQL文を2つに分けたらどうですか。
1.tとpを連結しtku_idでグループ化しMIN(post_id)で
最小値と必要項目を取得。
2.そのSQLと残りのテーブルを連結させて残りの必要な
項目を取得。

投稿日時 - 2006-03-03 15:57:52

お礼

回答ありがとうございます。
2つに分けるやり方でやってみましたが、構文が違うのかうまく
いきませんでした。
もうすこしがんばってみたいと思いますが、具体的にどういうSQL文に
なるのか教えていただけるとたすかります。

お手数おかけして申し訳ないです。よろしくお願いします。

投稿日時 - 2006-03-04 00:42:17

あなたにオススメの質問