パフォーマンスの良いSQLの書き方

このQ&Aのポイント
  • SQL初心者でもパフォーマンスを考慮したSQLの書き方を学びましょう。
  • 社員情報を管理するマスタテーブルとログテーブルから最新のログイン日付を取得する効率的なSQLの書き方を解説します。
  • クエリを改善してパフォーマンスを向上させる方法について学びましょう。
回答を見る
  • ベストアンサー

(初心者です)パフォーマンスの良いSQLの書き方

SQL初心者です。初歩的かもしれませんが 教えていただけると助かります。 社員情報を管理するマスタテーブル『MST』(PKはSHAIN_ID)、 社員のシステムログイン履歴をログとして残すテーブル『LOG』 (PKはSEQのみ、SHAIN_IDとLOGIN_DATEを持つ) があります。 社員ごとに最新のログイン日付を表示するとき、 以下のようなSQLを書いたところ「パフォーマンス上あまりよくないSQL」 と言われてしまったのですが、どのように改善すればよいでしょうか? ------------------------------------------ SELECT MST.SHAIN_ID,     MST.SHAIN_NAME,     LOG.LOGINTIME FROM  MST,    (SELECT LOGINUSERID,        MAX(LOGINDATE) LOGINDATE     FROM LOG     GROUP BY SHIAN_ID    ) LOG WHERE MST.SHAIN_ID = LOG.SHAIN_ID ORDER BY    MST.SHAIN_ID ------------------------------------------

  • m-m-
  • お礼率37% (23/61)

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

  • ベストアンサー
  • Mizyu
  • ベストアンサー率41% (245/593)
回答No.1

ぱっと思いついたのは -- SELECT MST.SHAIN_ID, MST.SHAIN_NAME, MAX(LOG.LOGINTIME) FROM MST, LOG WHERE MST.SHAIN_ID = LOG.SHAIN_ID GROUP BY MST.SHAIN_ID, MST.SHAIN_NAME ORDER BY MST.SHAIN_ID; -- ※動作検証していませんので、動作保障はしません。 パフォーマンスが悪い理由はFROM句にクエリーを使っていることです。 必要なとき以外は使わないほうがよいです。

m-m-
質問者

お礼

ありがとうございました。 大変参考になりました。

関連するQ&A

  • SQLについて

    SELECT YKC.code FROM ( SELECT code,seq FROM Ctable C,Dtable D WHERE C.num = D.num AND C.DATE <= '05/01/01' ) YKC GROUP BY code,seq HAVING YKC.seq = MAX(YKC.seq) のように記述したのですが、 HAVING YKC.seq = MAX(YKC.seq)の部分が働いてくれず 複数行取ってきてしまいます。 seqがMAXの1行だけを取得したい場合、 どのようなSQLにすれば良いでしょうか?

  • SQL文作成のお願い

    前提として下記のようなテーブルがあります。 テーブル名:test フィールド: 1)id: varchar, not null 2)name: varchar 3)date: timestamp with time zone, not null このテーブルに下記のようなレコードがあります。 '00001', 'A', '2005-01-01 00:00:00' '00001', 'B', '2005-07-01 00:00:00' '00001', 'C', '2005-11-01 00:00:00' '00002', 'X', '2005-01-20 00:00:00' '00002', 'Y', '2005-07-20 00:00:00' '00002', 'Z', '2005-11-20 00:00:00' ■今やりたいこと このテーブルからidごとにdateフィールド値が最近のレコードを取得したい。 ■やってみたこと 下記SQLを発行しました。 >select id, max(date) from test group by id order by id 結果==> 00001 2005-11-01 00:00:00 00002 2005-11-20 00:00:00 実際はnameフィールドの値も取得したいのですが、group by句を使うとフィールド指定ができませんでした。 ■だめだったSQL select id, name, max(date) from test group by id order by id どのようにSQLを書けばよろしいでしょうか?

  • SQLで取得したフィールドをSQL文として利用

    お世話になっております。 MYSQLで sql_id (int PK) sql_data (text) のようなテーブル(sql_db)を持ち select sql_id from where (sql_data をsqlとして実行した結果 ) > 200 のように、フィールドから取得した値をSQLとして実行したりする方法はございますでしょうか。 ご教授よろしくお願いいたします。

  • SQL文で教えていただきたいのですが・・・

    現在、Windows版のMySQLを使っており、 webのサービスでログ解析を行っているのですが、初心者の私ではどうにもならなくなったのでご教授ください。 Table「info」:ユーザー登録DB | id | varchar(16) |←登録ID | name | varchar(50) |←登録名 | mail | varchar(50) |←登録メールアドレス Table「log」:ログインのログをとるテーブル | date | int(11) |←ログインした時間 | id | varchar(16) |←ログインしたID と言うデータベースがあり、登録ポリシーは「一つのメールアドレスで複数のIDを取得可能」というものです。 したがって、 aaa@bbb.com と言うメールアドレスで登録したIDは複数存在し、 AAA BBB CCC と言う3つをもっていることもあります。 ところが、ログはID単位でとっているため、メールアドレスが同じにもかかわらずこうなります。 +------------+-----+ | date | id | +------------+-----+ | 1068019110 | AAA | | 1068019200 | BBB | | 1068019209 | CCC | | 1068019210 | AAA | | 1068019213 | BBB | +------------+-----+ これでは、ログの集計をしても1人がログインした数を集計できません。メールアドレス別のログをとりたいのです。 単純に表にするのは select log.id, mail from log_login inner join info on info.id=log_login.id where mail='***@***.com' order by date; にすることでなんとかできたのですが、別に表にする必要はなく、アクセス数だけを知りたいのです。 どうやったらいいのでしょうか???

  • SQLの書き方

    以下の条件を取得したいのですがどのようなSQLを組めばいいか悩んでます。 テーブルA(列はC1,C2,C3,C4 PKはC1,C2です。) ■テーブルAのデータ C1  C2   C3   C4 1   1   50   備考1です。 1   2   75   備考2です。 2   1   25   備考3です。 3   1   75   備考4です。 3   2   90   備考5です。 3   3   50   備考6です。 ■取得したい結果 C1  C2   C3   C4 1   2   75   備考2です。 2   1   25   備考3です。 3   2   90   備考5です。 ■取得したい条件 C1でグルーピングしたなかでC3の値が一番大きな行を取得する。 現在は以下のようなSQLを書いています。 SELCT T1.* FROM テーブルA T1, (SELECT C1,MAX(C3) AS C3MAX FROM テーブルA GROUP BY C1) T2 WHERE T1.C1 = T2.C1 AND T1.C3 = T2.C3MAX もう少し簡単なSQLで出来そうですが、うまく思いつきません。 宜しくお願いします。

  • ASP + SQLにて

    お世話になっております。 このたびASPを使用し、SQL Serverへデータをいれ管理プログラムを作成しているのですが、一部データの取り出しがわからないのでご質問させていただきます。 SQL文を発行する際に、 strSQL = "select * from table1 left join table2 on table1.社員ID = table2.ID order by table1.ID desc" としております。 構造として table1にはID,日付,内容,社員IDがありまして table2にはID,社員名があります。 上記のSQL文を実行し、 <% response.write objRS("社員名") %> として社員名を出力しているのですが、 そのときtable1のIDを出力しようとして <% response.write objRS("ID") %> としたらtable2のIDが出力されてしまいました。 table1のIDを出力する方法はないのでしょうか? よろしくお願いいたします。

  • SQLのcount()とgroup by

    以下のようなテーブルがあったとき、 tbl1 id | score 1 | 100 1 | 200 1 | 300 2 | 200 2 | 100 3 | 300 3 | 400 3 | 500 3 | 600 idでまとめて個数を出すとすると、 SELECT count(*) FROM tbl1 group by id とすれば count(*) 3 2 4 と結果が返ってきますが、この結果にidを足して id | count(*) 1 | 3 2 | 2 3 | 4 というようなSQLはどうやって書けばいいのでしょうか? MySQLでは、 SELECT id, count(*) FROM tbl1 group by id と書けるのですが、これは標準的なSQLではNGなそうなので、気になって質問しました。 よろしくお願いします。

  • Delphi SQL

    Delphi+InteBase 何がわからないのか、わかっていない状況です。 dbExpressのSQLConnection・SimpleDataSet、DataAccessのDataSource、DataControlsのDBGridを利用しています。 SimpleDataSetのDataset.CommandTextに「SELECT * FROM テーブル名」とかSQL文を書くことによって、希望のデータが表示されることまでは理解できました。 「SELECT MAX(ID) FROM テーブル名」など値を返す場合は、どのようにしたらよいのでしょうか? またCommandText:='DELETE FROM テーブル名'とすると、エラーにはなりますが、テーブルは空になっているのでtry文できりぬけています。 根本的にSQL文をどこに記述したらよいのかわかっていません。 どなたか、お助けを・・・

  • シェルでSQLの結果を取得したい

    シェルスクリプトでSQLPLUSから、SQL文を実行させる事はできたのですが、そのSQLがSELECT文の時、その抽出した結果をシェルスクリプト上 、知りたいとき、どのようにすればわかりません。 SELECT した結果は必ず0個または1個です。 どなたかご教授ください。 sqlplus -S user/pass @${SQL_FILE} << EOF >log.txt EOF SQL_FILEの中身 select seq from A_table where ID = 1

  • 重複データからの取得方法を教えてください

    id s_no s_name ---------------- 1 001 aaaa 2 005 bbb1 3 005 bbb2 4 002 cccc 5 005 bbb3 6 005 bbb4 上のものがテーブルの内容です。取得したい結果が ---------------- 1 001 aaaa 4 002 cccc 5 005 bbb3 です。 試したSQLは select distinkd on (s_no) id,s_name from shain where id>=5 order by id desc select id,s_no,s_name from shain where id>=5 group by s_no order by id desc などです。 データベースがmdbなのでdistinkd onは使えませんでした。 もしかすると書式が違うのでしょうか?