* SQL Hacks ―データベースを自由自在に操るテクニック- [#f552050e] -作者: Andrew Cumming (著), Gordon Russell (著), 西沢 直木 (翻訳) -日付: 2010-01-27 #html{{ <iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=bomweb-22&o=9&p=8&l=as1&m=amazon&f=ifr&md=1X69VDGQCMF7Z30FM082&asins=4873113318" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe> }} [[Google Books でも一部読めます。>http://books.google.co.jp/books?id=VLeoDrCML94C&printsec=frontcover&source=gbs_v2_summary_r&cad=0#v=onepage&q=&f=false]] **SQL Hacks memo [#z8ae29b6] |>|>|~1章 SQLの基本| |1.|コマンドラインからSQLを実行する|MS SQL Server, Oacle, MySQL, MS Access, PostgreSQL, D2 へのコマンドラインからの接続。| |2.|プログラムからデータベースに接続する|C#, Java, PHP, Perl, Ruby からデーターベースに接続する。| |3.|条件付きINSERTコマンドを実行する|INSERT ... VALUES と, INSERT ... SELECT。| |4.|データベースの更新|UPDATE における、データーの交換ではテンポラリ領域は不要。| |5.|SQLを利用してクロスワードパズルを解く|| |6.|同じ計算を繰り返さない|サブクエリーや VIEW を使用して、SQL をシンプルにする方法。| |>|>|~2章 JOIN、UNION、VIEW| |7.|既存のクエリに手を付けずにデータ構造を変更する|テーブル変更や、VIEW を使用する方法。よく使用される手法。| |8.|行と列を絞り込む|Perl, Java, Ruby, C#, PHP でのバインド変数の使用方法。| |9.|インデックスで絞り込む|カーディナリティと、複合インデックス作成のコツ。| |10.|サブクエリをJOINに変更する|「サブクエリに集約関数が含まれていない場合、サブクエリは必要ない。」は名言。NOT IN を外部結合に書き替えるは使える。| |11.|集計用のサブクエリをJOINに変更する|サブクエリを GROUP BY HAVING を使用して JOIN に変更する方法。| |12.|複雑なデータ更新を単純化する|複雑な条件での UPDATE を記述する方法。| |13.|適切なJOIN形式を選択する|外部結合と内部結合の組み合わさった連鎖結合の場合、内部結合を外部結合に変更する必要がある。星形結合の場合は混在したままで良い。| |14.|組み合わせを作成する|CROSS JOIN を使用して、組み合わせを作成する。| |>|>|~3章 文字列の処理| |15.|LIKEを使わずにキーワードを検索する|MySQL → FULLTEXT インデックス、PostgreSQL → Tsearch2 モジュール、MS SQL Server → MS フルテキストエンジン、Oracle → ctxapp (Oracle Text)| |16.|複数の列から文字列を検索する|複数の列を CONCAT で連結させて LIKE 検索。遅そう。| |17.|アナグラムを解く|線形ハッシュ関数, 二次ハッシュ関数, 指数ハッシュ関数の作成方法。| |18.|メールアドレスをソートする|メールアドレスの分離方法。計算列(ファンクション)インデックスの作成方法。| |>|>|~4章 日付の処理| |19.|文字列を日付に変換する|Oracle なら TO_DATE 一発。| |20.|データの傾向をつかむ|ログデーターの移動平均を取る方法。| |21.|日付単位でレポートを作成する|月別に集計。日付の丸め。| |22.|四半期レポートを作成する|Oracle で MONTH, YEAR 関数はないが、EXTRACT 関数で代替できる。| |23.|第2火曜日を取得する|Oracle で曜日を求めるには TO_CHAR(date, 'D')を使用する。| |>|>|~5章 数値の処理| |24.|行をまたいで乗算する|EXP(SUM(LN(val))) を使用して、複利計算などの行をまたいだ乗算ができる。| |25.|残高を求める|自己完結(セルフジョイン)による、累積値の算出。Oracle では OVER句の使用で簡潔になる。| |26.|JOINが返さない行も結果に含める|外部結合。(またはユニオン。)| |27.|重なる範囲を特定する|日付範囲同士のオーバーラップを調査する。LEAST()とGREATEST()関数の使用で簡潔になる。| |28.|ゼロ除算を避ける|NULLIF() 関数を使用。| |29.|COUNT関数を使わずに件数を数える|CASE を使用した条件付きのカウント。| |30.|複数列の最大値を求める|GREATEST()関数(最小値の場合はLEAST()関数)を使用する。| |31.|集約された値をバラバラにする|宿泊開始日と宿泊日数から、宿泊トランザクションを作成。整数テーブルを使用するのがポイント。| |32.|「丸め誤差」に対処する|丸めてからサマリーするか、サマリーしてから丸めるか、どちらかに統一する。| |33.|明細と小計を一度で取得する|明細と小計をUNIONで結合。または、GROUPING SETS句を使用。| |34.|中央値を求める|テンポラリーテーブルの使用。| |35.|集計結果を図で表現する|SQL で棒グラフを描く。| |36.|2点間の距離を計算する|三角関数を使用し、二点の GPS 情報から距離を計算する。| |37.|請求書と振込額の帳尻を合わせる|消し込みのために、一致するデーターと一致しそうなデーターを見つける方法。| |38.|ミスによる桁の入れ替わりを発見する|2桁の入れ替わりは、差が 9 の倍数になる。(10*a+b)-(10*b+a)=9*(a-b) これを利用し、ミスした可能性の高いデーターを見つける。| |39.|累進課税を適用する|収入と累進税率表から、累進税率を求める。| |40.|順位を求める|Oracle では、RANK()関数を使用する。| |>|>|~6章 オンラインアプリケーション| |41.|Webサイトをテーブルに取り込む|XSLT で HTML からデーターを抜き出す。| |42.|SVGを使用してデータからグラフを作成する|データーベースから XML(SVG)を生成する方法。 Oracle では XMLElement()関数とXMLAttributes()関数を使用すると簡潔。| |43.|Webアプリケーションにページナビゲーションを追加する|A~Z の目次を作成する。| |44.|Microsoft. AccessからMySQLに接続する|SSH と MySQL ODBC Connector を使用する。| |45.|Webサーバのログを処理する|http の access.log を perl を使用してデーターベースに取り込む。リンク切れ、ページ内移動の調査。| |46.|データベースに画像を保存する|BLOBを使用する方法。ファイル名を格納する方法。| |47.|SQLインジェクションの脆弱性とは|SQL インジェクション攻撃の例。| |48.|SQLインジェクション攻撃を防ぐ|Perl, C#, PHP, Java でのエスケープ方法。DBアカウントの権限を制限。| |>|>|~7章 さまざまなデータ構成| |49.|過去のデータも保存しておく|価格変更情報を持っている価格マスターから現在や指定日の価格を取得する方法。| |50.|構造の異なるテーブルを結合する|UNION の使用。| |51.|行を列として表示する|縦持ちを横持ちに変換する方法。自己結合か CASE 文を使用する。| |52.|列を行として表示する|横持ちを縦持ちに変換する方法。UNION を使用する。| |53.|矛盾するデータを削除する|正規化されていないデーターの矛盾を GROUP BY HAVING COUNT()>1 で見つける。| |54.|テーブルを非正規化する|INSERT SELECT JOIN で問い合わせ結果をテーブルに出力する。| |55.|外部データをインポートする|外部から取り込んだ更新できない表と、自分で更新する部分のみ表を分ける。| |56.|二人の仲を取り持つ|縦持ちしている属性同士のマッチング。NOT IN (SELECT) を使用する。遅そう。| |57.|一意の連番を作成する|Max()+1、Oracle の SEQUECE オブジェクト。※人工的な主キーは避けるべき?| |>|>|~8章 小さいデータの格納| |58.|データベースにパラメータを保存する|1レコードしか格納できないテーブルの作成。1レコードしかないので CROSS JOIN しても問題ない。| |59.|ユーザごとのパラメータを定義する|データーベースのユーザーを(Oracle の場合) USER で取得し、その値で絞り込む。| |60.|ユーザごとのパラメータリストを作成する|上記 59. のバリエーション。| |61.|行単位でセキュリティを設定する|データーベースユーザーを使用した、アクセスコントロールの例。| |62.|テーブルを参照せずにクエリを実行する|(Oacle 場合) dual 表を使用。SYS_GUID()は使いどころがありそう。| |63.|テーブルを使わずに行を生成する|UNION で定数を返す SELECT を連結し、サブクエリーで表のように使用する。テーブルの作成権限がないがクエリーのために小さな表を作成したい場合に使用出来そう。| |>|>|~9章 ロックとパフォーマンス| |64.|分離レベルを決定する|アイソレーションの話。ファントムリード、反復不可能読み取り、ダーティーリード。| |65.|悲観的ロックを使用する|変更する予定のレコードだけを FOR UPDATE でロックする。| |66.|楽観的ロックを使用する|ロックは使用せずに、更新時に他者が更新していないフラグで絞り込む、更新結果の件数が予定どおりなら OK、そうでないならロールバックする。| |67.|トランザクションで暗黙的にロックする|複数のデーター更新を 1 行の UPDATE で実現する。(SET に CASE 文で条件を記述。) これならロックは不要。| |68.|送信ボタンの連続クリックに対処する|ステータスでコントロールする。| |69.|データベース内で各処理を実行する|プログラムで処理するか、データーベースで処理するか。| |70.|クエリの実行結果を結合する|UNION でデーターベースへの問い合わせ回数を減らす。| |71.|大量の行を取得する|データー検索を、データーベースとプログラムで分担する方法。| |72.|指定件数の結果を取得する|ページング処理。例では FETCH を使用せず、ROWNUM で絞り込んでいるので、ひどく重い SQL になっている。| |73.|データの保存先としてファイルも利用する|同じディレクトリにファイルを置きすぎない工夫は良いと思うが、SQL としては見るべきものなし。| |74.|テーブルを比較して同期をとる|diff みたいなものを SQLで実現。| |75.|1対多形式のJOINが返すデータ量を減らす|ヘッダーと明細のジョインは、ヘッダー部分の重複があるので、ヘッダーと明細を UNION で結合し、ネットワークトラフィックを下げる例。| |76.|大きなデータは圧縮する|perl の Compress::Zlib でテキストを圧縮して保存する方法。当然ながら検索対象にできない。| |>|>|~10章 レポートの作成| |77.|データのないカテゴリもピボットテーブルに含める|Excel のピボットテーブル用に欠測値を生成する。外部結合や UNION を使用。| |78.|データを範囲ごとに区切る|年齢を20代や30代、日付を今月や来月のように、集計単位を変更する。かなり重いSQL。| |79.|更新する行を特定する|DBMS の機能でなく、SQL でレプリケーションを実現する方法。使わない方が無難では?| |80.|「ケビン・ベーコンの6次」を表現する|知り合いの知り合いをたどっていくと6人でどんな人にもたどり着くというやつ。| |81.|ディシジョンテーブルを作成する|送料を決定するためのテーブル(ディシジョンテーブル)を作成し、送料を算出する例。| |82.|連続値や欠測値を生成する|整数が格納された整数表、連続した日付の格納された日付表の作成方法と、外部結合での欠損値の調査。| |83.|各グループの上位の値を取得する|Oracle なら ROWNUM を使用すれば良いが、使用できない場合の SQL。| |84.|列にカンマ区切りリストを保存する|カンマで区切ったデーターをそのまま DB に保持する方法。| |85.|ツリーを横断する|例は家系図だが、組織表や BOM などに使用可能なテクニック。Oracle の階層問い合わせも紹介されている。| |86.|データベースでキューを利用する|FIFO キューの実現。| |87.|カレンダーを生成する|カレンダーを SQL で作成する。| |88.|サブクエリの抽出条件に2つの値を使う|副問い合わせに WHERE (Col1, Col2)=(SELECT Col1, Col2 ...) と記述する。| |89.|5つの項目から3つを選択する|求職者とスキル表から、少なくとも求める 5 つのスキルのうち三つを満たしている求職者を検索する方法。GROUP BY HAVING を使用する。| |>|>|~11章 ユーザと管理| |90.|ユーザアカウントを実装する|パスワードのハッシュ作成方法が興味深い。Oracle では、dbms_crypto ライブラリを使用する。| |91.|テーブル定義のエクスポートとインポート|Oracle だと、imp と exp。| |92.|アプリケーションを配置する|本番環境設定時の注意点。| |93.|データベースユーザを自動作成する|Unix で、Unix のアカウントと DB のアカウントを同時に作成する方法。| |94.|一般ユーザと管理者を作成する|DB 管理者ユーザー(DBA)作成時のポイント。| |95.|自動更新を実行する|トリガーの作成。| |96.|行動監視用のログを記録する|トリガーで更新ログを取る。| |>|>|~12章 幅広いアクセス| |97.|匿名アクセスを許可する|許可する前に、アカウントを制限する。| |98.|長時間実行されているクエリに対処する|Oracle では V$SESSION 表を参照する。| |99.|ディスクを使い果たさないようにする|テンポラリー領域の使い果たし、大きなテーブルの調査。| |100.|ブラウザからSQLを実行する|Oracle では iSQL*Plus。| #vote(参考になった[1],参考にならなかった[0]) #vote(参考になった[2],参考にならなかった[0])