• ベストアンサー
  • すぐに回答を!

次のデータ抽出を(高速に)行う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

共感・応援の気持ちを伝えよう!

  • 回答数3
  • 閲覧数194
  • ありがとう数3

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

  • ベストアンサー
  • 回答No.1
  • xKENx
  • ベストアンサー率65% (21/32)

「自分がフォローしている人のつぶやきと、じぶんの呟きを含めて、日付順で表示する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)

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

関連するQ&A

  • mysqlのsql文について教えて下さい

    mysqlのsql文について教えて下さい 下記のようなテーブルとデータがあった場合に どうやれば 2,次郎だけを抽出できますか? 本日日付(2010-08-06)が 既にテーブルBにdateが存在する場合は 3,1,2010-08-04 3,1,2010-08-06を 対象外にしたいです。 Aテーブル id,user 1,太郎 2,次郎 3,3郎 Bテーブル targetid,homonid,date(datetime型) 3,1,2010-08-04 3,1,2010-08-06 3,2,2010-08-05 下記だと2010-08-04にヒットしてしまい(当たり前?)動作しません。 select distinct a.* from tblA a, tblB b where date_format(b.date, "%Y-%m-%d") <> "2010-08-06" ;

  • グループ中で最大値を含む行を抽出するSQLはどう書けば良いでしょうか

    列A,Bでグループ化し、グループ中で列Cが最大値の列を取得したいのです。 数百万件あるので極力低コストにしたく、 副問合せはINDEXが効かないと聞いたのですが、 それ以外思いつきませんでした。 副問合せしない方法はないでしょうか? また、副問合せの中でコストの低いSQLはどんなものでしょうか。 ■テーブルです 名前 型 CUST_ID CHAR(8) BRANCH_ID CHAR(4) VALID_DATE DATE MYDATA VARCHAR2(20) CUST_ID BRAN VALID_DA MYDATA 19740704 0000 06-01-01 comment0001 19740704 0000 05-12-01 comment0000 19740704 0000 06-02-01 comment0002 19740704 0001 06-01-01 comment0011 19740704 0001 06-03-01 comment0012 ■このような結果が欲しいのですが。。。 CUST_ID BRAN VALID_DA MYDATA 19740704 0000 06-02-01 comment0002 19740704 0001 06-03-01 comment0012 ■考えたSQLです(検証済) select a.cust_id,a.branch_id,a.valid_date,a.mydata from test a,(select cust_id,branch_id,max(valid_date) as mvd from test group by cust_id,branch_id) b where a.cust_id=b.cust_id and a.branch_id=b.branch_id and a.valid_date=b.mvd ; select a.cust_id,a.branch_id,a.valid_date,a.mydata from test a where not exists (select * from test b where a.cust_id=b.cust_id and a.branch_id < b.branch_id) ; select cust_id,branch_id,valid_date,mydata from test where (cust_id,branch_id,valid_date) in (select cust_id,branch_id,max(valid_date) from test group by cust_id,branch_id) ; select cust_id,branch_id,valid_date,mydata from (select cust_id,branch_id,valid_date,mydata,max(valid_date) over(partition by cust_id,branch_id) as mvd from test) where valid_date=mvd ;

  • 次の条件を満たすSQL文をご教示下さい。

    テーブル名: list no | first_name | last_name | comment ----+------------+-----------+--------- 1 | 太郎 | 山田 | ほげ 2 | 次郎 | 田中 | ふが 3 | 花子 | 山田 | ぴよ 4 | 三郎 | 佐藤 | ぴよ 5 | 太郎 | 山田 | ぴよ 6 | 次郎 | 田中 | ふー 7 | 三郎 | 佐藤 | ふー 8 | 花子 | 山田 | ふー 上記の表から同じ”last_name”を持つ人の”first_name”と”last_name”を重複無しで抽出する(下記のような結果)SQL文は作成可能でしょうか。 結果 first_name | last_name ------------+----------- 太郎 | 山田 花子 | 山田 宜しくお願いします。

その他の回答 (2)

  • 回答No.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 );

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

  • 回答No.2
  • root139
  • ベストアンサー率60% (488/809)

現状で使われている 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

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

関連するQ&A

  • 2つのテーブルをひとつのテーブルとして表示

    お世話になります ■概要 Accessで2つのテーブルを1つにして表示させるにはどうしたらいいでしょう? ■詳細 サンプル1とサンプル2のテーブルが2つあるとします (サンプル内の列名はすべて同じです) それをひとつのクエリで表示させたいのですが(よに表示ではなく同じ列に表示させたいです サンプル1 ID|名前|年|  1|太郎|4 | 2|次郎|6 | サンプル2 ID|名前|年|  1|五郎|2 | 2|三郎|1 | 結果クエリ1 名前|年| 太郎|4 | 次郎|6 | 五郎|2 | 三郎|1 | わかる方ご教授願います

  • SQL文について教えてください。

    お世話になります。 テーブルを3つ作りました ユーザーテーブル:USER_MS USE_NO USER_NAME 001   太郎 002   次郎 003   三郎 品名テーブル:HINMEI_MS HINMEI_NO HINMEI_NAME 001    りんご 002    みかん 003    イチゴ 嫌いなものテーブル:KIRAI_TR KIRAI_NO USER_NO HINMEI_NO 001001  001   001 002003  002   003 002001  002   001 ※KIRAI_NO=USER_NO.HINMEI_NO と連結してプライマリーキーにした ここで、次郎の嫌いなものを抽出するときには $USER_NO = '002'; $SQL ="SELECT * FROM KITAI_TR A,HINMEI_MS B WHERE A.USER_NO = '$USER_NO'; で抽出できるのですが、 次郎の嫌いでない002みかんだけを抽出するSQL文がわからず苦慮しています。 以前、オラクルでSQLを使ったことがあったのですが、その時はFROM句の後に(SELECT * FORM・・・・) Bなどと書くと通ったのですがMYSQLでは通りませんでした。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • SQLの条件抽出について

    ちょっと躓いてしまったのでアドバイスが頂けたらと思います。 user_accountというテーブルと、logというテーブルがあります。 logというテーブルには各ユーザーの書き込み履歴が残されており、日付がtimestamp形式で格納されています。 ユーザー一覧に最終発言内容をくっ付けて表示したいのですがうまくいきません。 SELECT DISTINCT * FROM user_accounts LEFT JOIN (SELECT * FROM log ORDER BY update_date DESC ) aaa ON user_accounts.pkey = aaa.user_accounts_pkey; などと記述してみましたが、思うような結果になりません。 自分の理想とする結果は以下のような出力結果です。 +----+----+----+--+-----------------+----------------+-----------+ | pkey| user| pass|      comment| update_date| +----+----+----+--+-----------------+----------------+-----------+ |  1 | test1| pass01|test03 written by test1| 40813| |  2 | test2| pass02|testestest        | 40690| どうか、お知恵を貸してください。

  • mysqlでSELECTの速度を上げる方法

    以下のようなSQLを発行すると、mysqlの処理時間が非常に多くかかるため、なんとか最適化を行いたいと考えています。 どのような方法があるのか教えていただけませんしょうか。 SELECT user_id,comment,comment_id,date,study_time,study,source FROM data_temp t1 WHERE NOT EXISTS (select comment_id from data t2 where t1.comment_id = t2.comment_id) ■補足 ・dataとdata_tempのテーブル構造は全く同じです。 ・SQLで実現したいことは、両テーブルのcomment_idをキーとして、dataに含まれないdata_tempの差分データを表示させたい。 なお、以下のインデックス作成は行いましたが、結果変わらずでした。 alter table data t1 ADD INDEX_t1 (user_id,comment,comment_id,date,study_time,study,source); alter table data_temp t1 ADD INDEX_t1 (user_id,comment,comment_id,date,study_time,study,source); よろしくお願いします。

    • ベストアンサー
    • MySQL
  • MySQLのサブクエリーでエラーがでます

    現在MySQLを使って開発をしています。 SQLもMySQLもまだあまり使ったことがないのでなにか大きな勘違いをしている かもしれませんが、自分で作ったデータベースにMysqlコマンドでアクセスし、 以下のようにselectを行うとsyntaxエラーが発生します。 mysql> select CREATE_DATE from user where cust_id = (select cust_id from customer where memo = 'memo'); ERROR 1064: You have an error in your SQL syntax near 'select cust_id from customer where memo = 'memo')' at line 1 しかしサブクエリーの内容も、その前のselectもそれぞれ下記のように単体で実行すると正常に動作するので、文法的には間違っていないと思います。 ERROR 1064のsyntaxエラーは何を指しているのでしょうか? ぜひご教示ください。 mysql> select cust_id from customer where memo = 'memo'; +---------+ | cust_id | +---------+ | 1 | +---------+ 1 row in set (0.00 sec) mysql> select CREATE_DATE from user where cust_id = '1'; +-------------+ | CREATE_DATE | +-------------+ | 2001-07-23 | +-------------+ 1 row in set (0.00 sec)

  • サブクエリの使い方

    Table t1には t1code|t1type ------------------ 花子|1 太郎|1 一郎|2 次郎|2 五郎|2 Table t2には t2code|date ----------------- 太郎|2012-05-30 太郎|2012-05-30 花子|2012-05-10 花子|2012-05-10 次郎|2012-03-20 五郎|2012-04-10 一郎|2012-03-01 と登録されている場合に t1type毎に一番新しいdateをもつt2codeを抽出したいのです。 そこで、 select t2code,max(date) from t1 inner join t2 on t1code = t2code where (t2code,date) in (select t2code,max(date) as d from t2 group by t2code) group by t1type としたところ、 +--------+------------+ | t2code | max(date) | +--------+------------+ | 太郎 | 2012-05-30 | | 次郎 | 2012-04-10 | +--------+------------+ となります。 本来は、次郎→五郎になってほしいのですが、 どこが悪いのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • Excelのドロップダウンリストについて

    Sheet1において, A列 B列 1 田中太郎 2 佐藤次郎 3 山田三郎 のようなリストを作成してあるとします。 Sheet2において, A1のセルに1を入力すると,B1のセルに田中太郎と表示される様,B1にVLOOKUP($A1,Sheet1!$A$1:$B$3,2,0)と入力しています。 この時,A1をドロップダウンリストで入力する場合,リストの表示と入力値を変更するようなことはできるのでしょうか。 すなわち,リストには, 田中太郎 佐藤次郎 山田三郎 と表示され, 田中太郎 を選ぶとA1には1が入力され,B1にはVLOOKUP関数の効果として田中太郎と表示されるといった具合です。 当方,HTMLは理解しておりますので,HTMLで意図をご説明させていただければと思います。 HTMLでプルダウンボックスを使う場合の入力として, <SELECT name="ボックス名"> <OPTION value="1">田中太郎</OPTION> <OPTION value="2">佐藤次郎</OPTION> <OPTION value="3">山田三郎</OPTION> </SELECT> ということになります。 これと同じようなことがエクセルで可能なのかどうかという質問でございます。

  • マクロかエクセル関数教えて下さい。

    エクセルマクロ及び関数式で教えていただけないでしょうか?       月  火  水  木  金 太郎   ○ 花子         ○ 一郎      ○ 次郎             ○ 三郎          ○ 担当者名 太郎 一郎 三郎 花子 次郎 このように、丸が入ると担当欄のセルに「担当者名:月は太郎、火は一郎‥」を自動表示させたい。 1.そのセルに関数式 2.マクロ(サンプル) を、ご教授してくださる方が、おられましたら宜しくお願い致します。 これでご覧になれますでしょうか? ↓ http://firestorage.jp/download/37abd45beb74cb129a16bd3a92042647c013... 宜しくお願い致します。

  • 売上げ件数順のSQLについて

    売上げ件数順のSQLについて ユーザーごとに、日別の売上データを下記のSQLで集計しています。 これを、グループ化を保ったまま、全期間での売上げ件数合計の多いユーザー順に並び替えるにはどうすればよいでしょうか? select w.user_id as user_id, DATE_FORMAT(w.created_at,"%Y-%m-%d") as days,w.type as type, count(*) as num from uriage w group by user_id,type,days order by user_id,days,type; +---------+------------+-----------------+-----+ | user_id | days    | type      | num | +---------+------------+-----------------+-----+ |    1 | 2010-10-15 | カテゴリ1   |  1 | |    1 | 2010-10-15 | カテゴリ2   |  1 | |    1 | 2010-10-15 | カテゴリ3   |  5 | |    1 | 2010-10-16 | カテゴリ2   |  1 | |    1 | 2010-10-16 | カテゴリ3   |  1 | |    2 | 2010-10-15 | カテゴリ1   |  1 | +---------+------------+-----------------+-----+

  • 日付型(時刻含む)を抽出条件にして行を抽出したい。

    はじめまして、よろしくお願いします。 現在SQLサーバー2000を使用してこの処理を行おうと思っております。 一度テーブルに格納したデータをSELECT文を使って抽出したい と思っているのですが、WHERE条件に日付型のフィールドを指定するとうまく行きません。(時刻が日付型のフィールドに入っている場合、うまくいきません。) やっていることは YMD(DATE型・主キー)、ID(VERCHAR型・主キー)、NAME(VERCHAR型) というのテーブル(テーブル名:MEIBO)に入っている 2002/02/02 14:10:55、0001、山田 太郎 というデータを 取込年月日、個人IDを指定して特定の列を取り出そうとしています。 SQL文は SELECT * FROM MEIBO WHERE YMD = '2002/02/02 14:10:55' AND ID = "0001' と記述していますが、一件もヒットしません。 DATE型のフィールドにはINSERTするときにGETDATE()をつかってシステム日付を 格納するようにしています。 GETDATE()ではなく、DATE()を使ってシステム日付を格納した 2002/02/02、0001、山田 太郎 という時刻の入っていないデータに対しては SELECT * FROM MEIBO WHERE YMD = '2002/02/02' AND ID = "0001' というSQL文でヒットするのですようです。 時刻が入ったらそのフィールドを抽出条件として使うことは無理なのでしょうか? 基本的な部分で勘違いしているのかもしれませんが なにかお気づきの点がありましたら、ご教授ください。