SQLチューニングについて

このQ&Aのポイント
  • SQLチューニングについて悩んでいる方への解決策
  • Accessでのデータ出力におけるパフォーマンスの向上方法
  • 結合条件のNZ関数によるnull値の処理方法
回答を見る
  • ベストアンサー

SQLチューニングについて

以前別のサイトで質問し、一旦は解決したつもりでしたが、クライアントから再度条件を 突きつけられてしまい、投稿させて頂きました。 (そちら側のサイトでは完了にしてあります。これがマルチスレッドにあたるならご指摘下さい。) -------------------------------------------------------------------- 現在ACCESSにてデータ出力を行なっておりますが、パフォーマンスが出なく悩んでおります。 環境:Windows XP + Access 2003 テーブルA(約18000件) 項目s 項目t 項目u 項目v ★やりたいこと  テーブルAのうち、項目s,t,uを集約して、集約結果が1件のものを  対象に全ての項目(s~v)を出力したい。 ★現在作成中のSQL SELECT sub02.s, sub02.t, sub02.u, sub02.v FROM テーブルA AS sub02 INNER JOIN ( SELECT s, t, u FROM テーブルA GROUP BY s, t, u HAVING COUNT(s) = 1 ) AS Sub01 ON Nz(sub01.s)=Nz(sub02.s) AND Nz(sub01.t)=Nz(sub02.t) AND Nz(sub01.u)=Nz(sub02.u) 上記SQLで実行すると8~10分程度掛かってしまいます。 結合条件のNZ関数については、どうしてもnullが入る項目がある為に この様にしてしております。 どなたかお知恵を拝借願いたいと思います。

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

  • ベストアンサー
  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.1

これではダメでしょうか? SELECT sub02.s, sub02.t, sub02.u, --sub02.v max(sub02.v) AS v FROM テーブルA AS sub02 group by s,t,u having count(*) = 1; グルーピング項目でないvをmax(minでも同じ)関数で取得するようにします。 ACCESSは殆ど使ったことがないので的外れかもしれませんが、 テーブルの読込が1回で済むので少しは良くならないでしょうか。

hikaru_kenken
質問者

お礼

集約関数でこういった使い方があったとは・・・。 正直、目から鱗でした。 パフォーマンスも数分だったのが、30秒足らずで完了しました。 本当にありがとうございました。

その他の回答 (1)

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.2

(1)テーブルAに(s,t,u)のインデックスを作成してください。 (2)その上で下記のSQLを実行してみてください。 SELECT * FROM テーブルA T1 WHERE NOT EXISTS ( SELECT 1 FROM テーブルA T2 WHERE T1.S=T2.S AND T1.U=T2.U AND T1.V=T2.V GROUP BY T1.S,T1.U,T1.V HAVING COUNT(*)>1 )

関連するQ&A

  • SQL文の最後に「;」はいらないのでしょうか?

    VBAのADOについて質問です。 SQL文の最後には「;」を付けなくちゃいけないものだと思っているのですが ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ Private Sub test_Click() Dim CN As ADODB.Connection Dim RS As ADODB.Recordset Set CN = CurrentProject.Connection Set RS = New ADODB.Recordset SQL = "SELECT * FROM Tテーブル" ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ でも問題なくコードが動きました。 SQL文の最後に「;」はいらないのでしょうか? ちなみに SQL = "SELECT * FROM Tテーブル;" でもエラーになりませんでした。

  • SQL文

    SQLの初心者です。 Aテーブル(a項目,b項目,c項目)とBテーブル(a項目,d項目,e項目)のテーブルがあります。 d項目順でAテーブルの項目のみ出力するにはどうしたらいいのでしょうか。 例えば次のSQL文ではd項目順で出力されますが結合の為、AテーブルとBテーブルの全項目が出力されます。 SELECT * FROM Aテーブル LEFT OUTER JOIN DITKM ON Aテーブル.a項目 = Bテーブル.a項目 ORDER BY Bテーブル.d項目 次のSQL文のようにAテーブルの項目を選択したらAテーブルの項目のみ出力する事はわかります。 SELECT a項目,b項目,c項目 FROM Aテーブル LEFT OUTER JOIN DITKM ON Aテーブル.a項目 = Bテーブル.a項目 ORDER BY Bテーブル.d項目 今回はAテーブルの項目数が少ないのでこれでもいいのですが、項目数が多くなると大変です。 上の様に項目を選択しないでAテーブルの項目を全て出力する事は可能なのでしょうか。 宜しくお願い致します。

  • SQLのSELECT文で*を使わない理由

    SQLでSELECT文を使う場合、大抵  SELECT ID, user FROM u_table のように、取得する項目を指定すると思います。 これを、  SELECT * FROM u_table としないのには、トラフィックの問題以外に何か理由があるのでしょうか?

  • 年齢分布テーブルの再集計SQL

    テーブルA 年齢,人数 20,15 21,11 22,26 .... 30,5 31,88 ... 60,5 上記テーブルAからのSQLで下記のデータが欲しいと思っております。 【欲しい結果】 年齢範囲,人数 20~24,50 25~29,33 30~34,199 ... ただし、 select '20~24'as 年齢範囲,count(*)as 人数 from テーブルA where 条件1 union select '25~29'as 年齢範囲,count(*)as 人数 from テーブルA where 条件2 union select '30~34'as 年齢範囲,count(*)as 人数 from テーブルA where 条件3 ... というSQLは使いたくないです。(テーブルAの記述が長めなので、同じものを複数記述したくないのです) また結果が 項目名:20~24,25~29,30~34,... レコード:50,33,199,... というのも遠慮したいです。 CASE文やsum、groupを使えば、できそうな気がするのですが、、、 ご教授お願い致します。

  • シンプルなSQLの書き方がわかりません。

    以下のSQLをシンプルに一つにしたいのですが、どのように書いたらよろしいでしょうか? どうぞご返答頂けますようお願い申し上げます。 --test1_tblの抽出 select a1 as a1, b1 as b1 from a_tbl where c=1 --test2_tblの抽出 select a1 as a1, e1 as e1 from b_tbl where rowid in (select min(rowid) from ee group by a1) and a1 is not null and a1 !=' ' order by a1 --test1_tblとtest2tblの結合 select t0.a1 as a1, t0.b1 as b1, t1.e1 as e1 FROM test1_tbl t0, test2_tbl t1 WHERE (t0.a1 = t1.a1)

  • SQL文のAS句の意味を教えて下さい。

    generate_seriesをネットで調べていたら下記のページを見つけ、このページのSQL文を解読していたら一か所、わからないところがあったので質問しました。 下記のSQL文はサイトからコピーしたものです。 SELECT  current_date + s.a AS date FROM  generate_series(   (SELECT 0 - extract(dow FROM current_date))::int,   (SELECT 6 - extract(dow FROM current_date))::int  ) AS s(a); 下記が上記のSQL文を実行した結果です。   date ---------- 2012-02-26 2012-02-27 2012-02-28 2012-02-29 2012-03-01 2012-03-02 2012-03-03 上記のSQL文のAS句を下記のように私が変更してSQL文を実行したら上記の結果と同じ結果を出力しました。 SELECT  current_date + s AS date FROM  generate_series(   (SELECT 0 - extract(dow FROM current_date))::int,   (SELECT 6 - extract(dow FROM current_date))::int  ) AS s; 下記が上記のSQL文を実行した結果です。   date ---------- 2012-02-26 2012-02-27 2012-02-28 2012-02-29 2012-03-01 2012-03-02 2012-03-03 上記のSQLのAS句の「s(a)」はどういう意味ですか? ※AS句は別名を付ける際に使うと思うんですが... すみませんが説明していただけませんでしょうか? 宜しくお願いします。

  • この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で名前の属性に「様」をつけて取り出したい場合はどうしたらいいのですか。 参考書に書いてあるようにやったのですが、そうすると0が出力されてしまいました。(もとのテーブルにはちゃんと名前が入っています) よろしくお願いします。 mysql> select customername || '様' as お名前 from customers; +--------+ | お名前 | +--------+ | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 |

    • ベストアンサー
    • MySQL
  • 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で出来そうですが、うまく思いつきません。 宜しくお願いします。

  • 動的SQL (その3)

    色々試したのですが、再現したりしなかったりで???状態です。 下記の状態は確認できたので質問したいと思います。 勤怠コードのクロス集計の為の実験をしています。 エクセル出力する形で実行しています。 必ず三つ目のexec命令を通っています。・・・経路をテーブルに出力して確認済み 結果はT_日報の件数が出力されています。・・・これはOK しかし列名が「xx」になってしまいます。・・・NG(「A0」にしたい) フィールドに値が入っていません・・・NG --------------------------------------------------- BEGIN if 'B0'='B1'   begin   exec sp_executesql N'SELECT 勤怠コード AS xx FROM T_勤怠'   end if 'B0'='A0'   begin   exec sp_executesql N'SELECT 勤怠コード AS B0 FROM T_勤怠'   end else   begin   exec sp_executesql N'SELECT 勤怠コード AS A0 FROM T_日報'   end END ------------------------------------------------------ よろしくお願いします。