SQLの速度改善について(小ネタ)

開発中のプログラムがあまり進んでないのでSQLの小ネタ。
昔、よくあった遅いSQLの改善方法について、記載。
インデックスを張ったりするのもいいけど、SQLを作るときにデータをたくさん持ってきてまとめて条件分岐をCASE式でするだけで
圧倒的に速度が改善できる。

例えば、業務アプリで帳票などを作成する際に、列に月の集計結果を、持たせようとするケースがよくある。

 2018年 

       1月|2月|3月|・・・・
得意先A    100|  60|  40|・・・・
得意先B      0|  20|  40|・・・・



こういう集計をSQL側でGroupByを何個も書いて集計していたりするのをよく見る。

(例)

      SELECT *
      FROM 得意先マスター AS 得意先
      LEFT JOIN (
         SELECT SUM(売上金額) AS 1月売上
                      ,得意先CD
          FROM 売上テーブル
            WHERE 年月 = '201801'
           GROUP BY 年月,得意先CD
        ) AS 1月売上金額

  ON 得意先.得意先CD = 1月売上金額.得意先CD
  以下、LEFT JOIN が11ヶ月分続く


しかし、やむを得ない場合なら仕方ないけど、特に考えもせずにこんなソースを書いている人がいると殴りたくなってくる。
実際に昔、こんな感じのSQLを発行して、メモリエラーが発生するんでどうしたらいいでしょう。みたいなことを言われたことがある。
その時には3万行のSQLを発行して使い物にならなかった。

SUM関数の中にCASE式を書くことができるので、下記のSQLで一気に12か月分のデータを取得できる。

(例)
      SELECT SUM(CASE WHEN RIGHT(年月,2) = '01' THEN 売上金額 ELSE 0 END) AS 1月売上
                   ,SUM(CASE WHEN RIGHT(年月,2) = '02' THEN 売上金額 ELSE 0 END) AS 2月売上
                   ,SUM(CASE WHEN RIGHT(年月,2) = '03' THEN 売上金額 ELSE 0 END) AS 3月売上
                   ,SUM(CASE WHEN RIGHT(年月,2) = '04' THEN 売上金額 ELSE 0 END) AS 4月売上
                   ,SUM(CASE WHEN RIGHT(年月,2) = '05' THEN 売上金額 ELSE 0 END) AS 5月売上
                   ,得意先CD
          FROM 売上テーブル
            WHERE LEFT(年月,4) = '2018'
           GROUP BY 得意先CD

件数のカウントとかも、「SUM(CASE WHEN RIGHT(年月,2) = '02' THEN 1 ELSE 0 END) AS 2月売上件数」とすることで
一つのSQL文で対応ができる。

Window関数を利用すればもっといろんなことができる。

意外と集計関数の中にCASE式が書けないことを知らない人がいたのでメモをしておく。
処理速度もSQLの文量も修正の手間も圧倒的に違うので、普段からある程度慣れ親しんでいてほしい。

SQLは慣れてくるとパズルみたいに思えてくるので、頭の体操としてはすごくいい感じ。

0 件のコメント:

コメントを投稿

PowerShellでEdgeを自動化(インストール不要。参考:郵便追跡サービス自動操作)

1.経緯について  RPAのソフトをインストールできないので、これまでVBSでCreateObjectでブラウザの自動操作をすることがたまにあった。 ※いざというときの手札として持っているだけで安心感が段違い  見た目上IEがインストールされていなくても、CreateObject...