こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

次のデータ抽出を(高速に)行うSQLを教えてくださ

自分がフォローしている人のつぶやきと、じぶんの呟きを含めて、日付順で表示するSQLを検討しています。
MYSQLの構文がかなり複雑になってしまったために、
もっと簡単に高速にSQLで記述する方法がありましたら教えて頂けませんでしょうか。
長文になり申し訳ございませんが、アドバイスいただけると幸いです。


テーブルは以下の3種類です。


●cutomer:登録者名を記録
<構造>
id(auto increment,key),name(名前)
<サンプルデータ>
0,"太郎"
1,"次郎"
2,"三郎"
3,"四郎"

●follow:誰が(my_user_id)、誰をフォローしているか(target_user_id)を記録
<構造>
id(auto increment,key),my_user_id,target_user_id
<サンプルデータ>
0,1,0
0,1,2

●tweet:つぶやきを記録
<構造>
id(auto increment,key),user_id,tweet_comment(つぶやき),date(つぶやき日時)
<サンプルデータ>
0,1,"次郎のつぶやきです","2011-01-01 00:00:00"
1,2,"三郎のつぶやきです","2011-02-01 00:00:00"
2,0,"太郎のつぶやきです","2011-03-01 00:00:00"
3,1,"次郎のつぶやきです","2011-04-01 00:00:00"
4,3,"四郎のつぶやきです","2011-05-01 00:00:00"



上記のサンプルデータを用いて、期待する出力結果をご説明します。
例として、入力値を「次郎」とすると、
「次郎」のつぶやきと、次郎がフォローしている太郎と三郎の呟きを表示したいです。

"次郎","次郎のつぶやきです","2011-01-01 00:00:00"
"三郎","三郎のつぶやきです","2011-02-01 00:00:00"
"太郎","太郎のつぶやきです","2011-03-01 00:00:00"
"次郎","次郎のつぶやきです","2011-04-01 00:00:00"



現状は、次郎とつぶやきselectと、次郎がフォローする太郎と三郎のつぶやきselectを
unionで結合する形式なっており、もうちょっと賢くできないものかと悩んでいます。
なお、対象の次郎のuser_id(サンプルでは"1")は予めわかっているものとします。

(
select customer.name,tweet.tweet_comment,tweet.date
from customer,tweet
where customer.id = 1 and customer.id = tweet.user_id
)
union
(
select customer.name,tweet.tweet_comment,tweet.date
from customer,tweet,follow
where follow.my_user_id = 1 and follow.target_user_id = tweet.user_id
and tweet.user_id = customer.id
)
order by table_tweet.date asc

投稿日時 - 2011-07-27 21:49:09

QNo.6903808

すぐに回答ほしいです

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

「自分がフォローしている人のつぶやきと、じぶんの呟きを含めて、日付順で表示するSQL」
をそのままSQLにした感じで、下記はいかがでしょうか。
tweet.user_idにindexがあったほうが良いかもしれません。

1)SELECT customer.name, tweet.tweet_comment, tweet.date
2)FROM tweet
3)INNER JOIN customer ON customer.id = tweet.user_id
4)WHERE tweet.user_id IN (SELECT target_user_id FROM follow WHERE my_user_id = 1)
5)OR tweet.user_id = 1
6)ORDER BY tweet.date


説明
自分がフォローしている人→4)
自分の→5)
つぶやき→2)
日付順→6)

投稿日時 - 2011-07-28 00:08:37

お礼

わかりやすいご説明ありがとうございます。
INを用いる方法ですね。動作を確認したいと思います。

投稿日時 - 2011-07-31 16:27:20

ANo.1

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

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

-広告-
-広告-

回答(3)

ANo.3

alter table customer add key ( name );
alter table follow add key ( my_user_id );
alter table tweet add key ( user_id );

のINDEXを追加して

select customer.name, tweet.tweet_comment, tweet.`date`
from customer join tweet
on customer.id = tweet.user_id
where customer.name='次郎'
or exists
( select 1 from follow join customer on follow.my_user_id = customer.id
and customer.name ='次郎'
where tweet.user_id = follow.target_user_id );

投稿日時 - 2011-07-28 12:07:51

お礼

早々のご回答ありがとうございます。
INDEX追加などDBを理解して動作を確認したいと思います。

投稿日時 - 2011-07-31 16:29:08

ANo.2

現状で使われている UNION でつないだ2つのSELECTの内、後半のものには全てのテーブルの情報が含まれているので、followを外部結合にして両方の条件をWHERE 句に並列に並べれば、前半のSELECT は不要になるかと。

例) -------------------------------------------------
SELECT customer.name, tweet.tweet_comment, tweet.date
FROM
tweet
INNER JOIN customer ON (tweet.user_id = customer.id)
LEFT OUTER JOIN follow ON (tweet.user_id = follow.target_user_id)
WHERE customer.id = 1 OR follow.my_user_id = 1
ORDER BY date ASC
-----------------------------------------------------

もしくは、「つぶやいたユーザーに対する次郎のフォローが存在している」という条件を相関サブクエリーを使って表現しても良いでしょう。

例) -------------------------------------------------
SELECT customer.name, tweet.tweet_comment, tweet.date
FROM customer, tweet
WHERE
customer.id = tweet.user_id AND
(
customer.id = 1 OR
EXISTS (
SELECT * FROM follow
WHERE tweet.user_id = follow.target_user_id AND follow.my_user_id = 1
)
)
ORDER BY date ASC
-----------------------------------------------------

参考URL:http://codezine.jp/article/detail/907

投稿日時 - 2011-07-28 00:31:25

お礼

早々のご回答ありがとうございます。
外部結合でも対応できそうですね。
動作を確認したいと思います。

投稿日時 - 2011-07-31 16:28:14

-広告-
-広告-

あなたにオススメの質問

-広告-
-広告-