キムラデービーブログ

オープンソースデータベースを加速する「キムラデービー」のブログです。カレー日記を兼ねてます。なお著者は2010-06-01より日本オラクルに在籍していますが、本サイト(ブログ、またはウェブサイト)において示されている見解は、私自身の見解であって、オラクルの見解を必ずしも反映したものではありません。
<< MySQLユーザ変数を使った高速dense_rank() | main | OSC2008島根、その前に「島根大学の研究プロジェクト」 >>
MySQLユーザ変数を使った高速rank()
0
    前回と同様にユーザ変数を使って、rank()を実装してみます。基本的な考え方は前回と同じですが、各行をシーケンシャルにカウントするための変数@rownumを用意し、(@preval = sal)が等しくなければ@rownumを返すようにします。各行を値を返さずに@rownumをカウントアップするために、IF()の条件のところに、(@rownum := @rownum + 1)を置いています。これは、必ずTRUEになるため、カウントアップする処理をするだけです。

    [2008-12-24 追記]
    比較をNULLセーフなもの(<=>)に変更し、@rnkの初期化を入れ、以前あった問題が起きないように改善しました。salにNULLがないことを前提にしています。

    --Like rank()
    set @rnk=0, @rownum=0, @preval=null; select @rnk:=IF((@rownum := @rownum + 1) and (@preval <=> sal), @rnk, @rownum) AS rnk, @preval:=sal sal FROM emp order by sal;

    +------+------+
    | rnk | sal |
    +------+------+
    | 1 | 800 |
    | 2 | 950 |
    | 3 | 1100 |
    | 4 | 1250 |
    | 4 | 1250 |
    | 6 | 1300 |
    | 7 | 1500 |
    | 8 | 1600 |
    | 9 | 2450 |
    | 10 | 2850 |
    | 11 | 2975 |
    | 12 | 3000 |
    | 12 | 3000 |
    | 14 | 5000 |
    +------+------+
    14 rows in set (0.00 sec)
    | meijik | MySQL | 11:36 | comments(5) | trackbacks(0) | - | - |
    接続して初回実行時だけ、NULLがまじる現象が確認できています。対策考えますので、しばしお待ちを。

    mysql> set @rownum=0, @preval=null; select @rnk:=IF((@rownum := @rownum + 1) and (@preval = sal), @rnk, @rownum) AS rnk, @preval:=sal sal FROM emp order by sal;
    Query OK, 0 rows affected (0.00 sec)

    +------+------+
    | rnk | sal |
    +------+------+
    | 1 | 800 |
    | 2 | 950 |
    | 3 | 1100 |
    | 4 | 1250 |
    | NULL | 1250 |
    | 6 | 1300 |
    | 7 | 1500 |
    | 8 | 1600 |
    | 9 | 2450 |
    | 10 | 2850 |
    | 11 | 2975 |
    | 12 | 3000 |
    | NULL | 3000 |
    | 14 | 5000 |
    +------+------+
    | MeijiK | 2008/10/04 4:14 PM |
    Blog本文のほうは修正しました。これで殆どのプラットフォームで大丈夫です。

    本来は、@rnkを初期化しなくても動作するはずなので、バグデータベースに登録しました。

    http://bugs.mysql.com/bug.php?id=41741
    | MeijiK | 2008/12/27 4:33 PM |
    OracleSQLパズルにリンクしていただきありがとうございます。

    こんなエントリを私のブログに書いたことがあるのですが、
    英語の堪能な木村さんはどう思われますか?
    いや、私は、日本語のマニュアルしかまともに読めないので

    ---------------------------------------------------------------
    2008年11月1日(土)
    あれまあ
    MySQLのユーザ変数で、分析関数を模倣できると思ったんですが・・・
    order by句のソート順で、かつ、select句の左から順で、
    評価が保証されないと、ほとんど使い道はなさそうですね。

    MySQL 5.1 リファレンスマニュアル :: 8.4 ユーザによって定義された変数
    >ユーザ変数の評価順序は定義されておらず、与えられたクエリ内の要素に基づいて変更されることがあります。
    >SELECT @a, @a := @a+1 ...では、MySQLは@aを先に評価し次に割り当てが実行されるように見えますが、
    >クエリの変更(例えばGROUP BY、HAVINGまたはORDER BY節による変更)は評価順序を変更する可能性があります。
    >
    >基本的なルールは、
    >ステートメントの一部でユーザ変数値を割り当てないことおよび
    >同一ステートメント内の他部分で同じ変数を使用しないことです。
    >期待通りの結果を得られるかもしれませんが、
    >これは確約されていません。

    MySQL 5.1 Reference Manual :: 8.4 User-Defined Variables
    >The order of evaluation for user variables is undefined and
    >may change based on the elements contained within a given query.
    >
    >In SELECT @a, @a := @a+1 ...,
    >you might think that MySQL will evaluate @a first and then do an assignment second,
    >but changing the query (for example, by adding a GROUP BY, HAVING, or ORDER BY clause)
    >may change the order of evaluation.
    >
    >The general rule is never to assign a value to a user variable in one part of a statement
    >and use the same variable in some other part of the same statement.
    >You might get the results you expect, but this is not guaranteed.
    | 明智重蔵 | 2009/01/05 8:10 PM |
    英語については、毎日蟹工船な私ですが(笑)

    まさに明智さんと同じとこを参照されて、登録したバグ票が「修正しない(Won't Fix)」で戻ってきました。

    ということで、この手法自体は動くかもしれないけど、保証しない、ということで。しくしく。
    | MeijiK | 2009/01/07 1:39 AM |
    かなり面白いテクニックですね。
    一捻りして、グループ毎の上位n件を取得するというのをやってみました。

    テーブルxxx( nen, gaku )に対して

    set @rnk = 0, @prenen = null,@pregaku = null;
    select nen,gaku,rnk
    from
    (select
    @rnk := if( @prenen <=> nen, if( @pregaku <=> gaku, @rnk, @rnk+1 ), 1 ) as rnk
    ,@prenen := nen nen
    ,@pregaku := gaku gaku
    from xxx
    order by nen,gaku desc
    ) t
    where rnk <= <取得したい件数>;

    OracleやDB2、SQLSEERVER、PostgresqlなどではWINDOW関数使えるんですが、MYSQLにはありません。
    相関問合せでも出来るんですが件数が多くなるとパフォーマンス的に厳しいので、案外使い道があるかもしれません。
    | ノラ | 2011/03/15 7:40 PM |









    http://blog.kimuradb.com/trackback/681085
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    << December 2017 >>
    + RECOMMEND
    100人のプロが選んだソフトウェア開発の名著 君のために選んだ1冊
    100人のプロが選んだソフトウェア開発の名著 君のために選んだ1冊 (JUGEMレビュー »)

    100人のうちの一人としてミックさんの本を推薦しています。
    + RECOMMEND
    MySQL 5.1 Plugin Development
    MySQL 5.1 Plugin Development (JUGEMレビュー »)
    Andrew Hutchings,Sergei Golubchik
    MySQL 5.1 のプラグインを作るならこれ!
    + RECOMMEND
    AWKを256倍使うための本 (Ascii 256倍)
    AWKを256倍使うための本 (Ascii 256倍) (JUGEMレビュー »)
    志村 拓,鷲北 賢,西村 克信
    ここにきてまさかの復刊。15〜16年前の本ですが、いまでも十分役立ちますよ!!
    + RECOMMEND
    Linux-DB システム構築/運用入門 (DB Magazine SELECTION)
    Linux-DB システム構築/運用入門 (DB Magazine SELECTION) (JUGEMレビュー »)
    松信 嘉範
    Linux-DB システム構築の新スタンダード。DB Magazine人気連載、待望の書籍化です!!
    + RECOMMEND
    + RECOMMEND
    超・極める!MySQL
    超・極める!MySQL (JUGEMレビュー »)
    坂井 恵,志村 和彦,ひろせ まさあき,松信 嘉範
    内容は少々古くなりましたが、内部説明があり、いろいろ面白いです。
    + RECOMMEND
    The Root of .NET Framework
    The Root of .NET Framework (JUGEMレビュー »)
    荒井 省三
    .NETの根っこをつかむ、か?
    + RECOMMEND
    エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド
    エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド (JUGEMレビュー »)
    奥野 幹也
    これまでにない構築、そして構築後のMySQLのための本。
    + RECOMMEND
    Database Management Systems
    Database Management Systems (JUGEMレビュー »)
    Raghu Ramakrishnan,Johannes Gehrke
    ミックさん連載の参考書籍です。
    + RECOMMEND
    Advanced Programming in the UNIX Environment: Paperback Edition (2nd Edition) (Addison-Wesley Professional Computing Series)
    Advanced Programming in the UNIX Environment: Paperback Edition (2nd Edition) (Addison-Wesley Professional Computing Series) (JUGEMレビュー »)
    W. Richard Stevens,Stephen A. Rago
    必読! といいつつ私が読んだのは初版の日本語訳です。差分はチェックしないといけませんね。
    + RECOMMEND
    + RECOMMEND
    + RECOMMEND
    Western Digital Scorpio Blue 2.5inch 5400rpm 320GB 8MB PATA WD3200BEVE
    Western Digital Scorpio Blue 2.5inch 5400rpm 320GB 8MB PATA WD3200BEVE (JUGEMレビュー »)

    DELL SX260の換装用に購入。今はコチラのほうが安いですね。
    + RECOMMEND
    情熱プログラマー ソフトウェア開発者の幸せな生き方
    情熱プログラマー ソフトウェア開発者の幸せな生き方 (JUGEMレビュー »)
    Chad Fowler
    OSC2010神戸に出展されたジュンク堂で買いました。
    + RECOMMEND
    Software Design 総集編 【2000~2009】(DVD付)
    Software Design 総集編 【2000~2009】(DVD付) (JUGEMレビュー »)

    メガトン級の過去記事。売り切れる前にお店に急げ!
    + RECOMMEND
    + RECOMMEND
    玄人志向 2.5型HDDケース SATA対応USB2.0接続 GW2.5AI-SU2
    玄人志向 2.5型HDDケース SATA対応USB2.0接続 GW2.5AI-SU2 (JUGEMレビュー »)

    Aspire 1410 HDD換装後、昔のHDDはこれにいれます。
    + RECOMMEND
    + RECOMMEND
    acer Aspire Timeline AS1410 11.6型ノートPC Windows7搭載 250GB ブラック AS1410-KK22
    acer Aspire Timeline AS1410 11.6型ノートPC Windows7搭載 250GB ブラック AS1410-KK22 (JUGEMレビュー »)

    色違い黒(他に青と白があります): メモリは最大4GBとあるが、がんばれば8GBいけるらしい。
    + RECOMMEND
    Firebird 徹底入門
    Firebird 徹底入門 (JUGEMレビュー »)
    木村 明治,はやし つとむ,坂井 恵
    Firebird日本ユーザ会のはやしさん、そしてMyNAから拝借(?) してきた坂井さんとともに書きました。まだ誰も知らないFirebird 2.5や、いままでドキュメントのなかったツール類についてもソースを確認してとりあげた本です。是非ご活用ください。
    + SELECTED ENTRIES
    + RECENT COMMENTS
    • 使い慣れたSQLに潜む実装依存: Firebirdの場合(6) 文字列との結合演算子
      noname (12/10)
    • 毎月日経SYSTEMSが届くたびに?が増え続ける: 日経SYSTEMSのコラム「ITアーキテクチャーの真髄」と「第7正規化」
      Moriaki_ (01/05)
    • 毎月日経SYSTEMSが届くたびに?が増え続ける: 日経SYSTEMSのコラム「ITアーキテクチャーの真髄」と「第7正規化」
      Moriaki_ (01/05)
    • 2015年版 InterBaseの歩み
      nakagami (12/06)
    • 毎月日経SYSTEMSが届くたびに?が増え続ける: 日経SYSTEMSのコラム「ITアーキテクチャーの真髄」と「第7正規化」
      meijik (11/22)
    • 分散DB本読書会第46回メモ「STOP AFTER 10」
      masudahidehiko (09/01)
    • Windows上でのMySQLビルド方法
      kinoyasu (03/31)
    • 気軽に新しいMySQLを試してみる: MySQL Sandboxのススメ
      MeijiK (09/19)
    • 伝わらない曲シリーズ: 川島恵「ミスター不思議」
      96 (07/05)
    • 気軽に新しいMySQLを試してみる: MySQL Sandboxのススメ
      MeijiK (02/17)
    + RECENT TRACKBACK
    + CATEGORIES
    + ARCHIVES
    + MOBILE
    qrcode
    + LINKS
    + PROFILE