キムラデービーブログ

オープンソースデータベースを加速する「キムラデービー」のブログです。カレー日記を兼ねてます。なお著者は2010-06-01より日本オラクルに在籍していますが、本サイト(ブログ、またはウェブサイト)において示されている見解は、私自身の見解であって、オラクルの見解を必ずしも反映したものではありません。
2018年のFirebird
0
    2018年のFirebird

    本エントリはFirebird Advent Calendar 2017の25日目です。

    さて、2018年のFirebird ! といえば、まずは次版のFirebird 4.0の話になります。

    ....と書いてこれは去年のエントリと同じ! うーん。

    話としては昨日naagamiさんの書いてくれた以下のとおりなのです。

    Firebird4.0 Planning Board 2017 update(ある nakagami の日記)

    今年はちょっと補足もないですが、以下の二つの事柄を。。。。

    1.Firebird Tour 2017: Performance seminars
    去年はカンファレンスが行われましたが、今年はFirebird Tourの2017年度版ということで行われました。
    # 2012までは毎年カンファレンスが行われていましたが、それ以降は隔年になっています。

    Firebird Tour 2017: Performance Optimization
    Firebird Conference 2016
    Firebird 2015 Tour: Big Databases
    Firebird 2015 Spring Tour
    Firebird Conference 2014
    Firebird 2013 Tour
    Firebird Conference 2012

     以下のページからそれぞれ二つずつのプレゼンテーションが公開されていますので、チェックしてみてください。

    Presentations from Firebird Tour 2017: Firebird Performance and Tuning Linux and Windows

    Presentations from Firebird Tour 2017: Firebird 3 Statistics and Plans and Advanced Trace API

     木村も最後に参加したのは2008年のイタリア開催なので、来年は久しぶりに参加してみたいですね。

    2.2018のデータベースが進む道とFirebird
     これまでのRDBMSはオンプレで、いかに性能をあげるか、HAを担保するのか、を競っていたように思えますが、
    ここ数年、主戦場はオンプレからクラウドに移行してきているように感じます。そして「世の中の "マネージド" を名乗るサービスがやってくれること」が徐々に進化して、開発者がオンプレでちまちまやるよりも、そこに「丸投げ」したほうがいい(楽?)な部分が徐々に増えていると思います。と、思ったのは以下のエントリ。

    最近MySQLをやめて別のRDBMSにしたときの話(MySQL Casual Advent Calendar 2017 12日目)

    DBAをある程度極めた人が超絶技巧的にチューニングするのであれば、オンプレでエンタープライズ要素の高いRDBMSを使えばよいのですが、そこらへんは適当でよくて、各種運用をしたくない人には"マネージド"を名乗るサービスを使ったほうが幸せになれる気がします。

     さて、Firebirdはどうでしょうか? Firebird自体はオンプレで超絶技巧的にチューニングするのには向いてないし、また"マネージド"のサービスに乗ったり、Amazon Auroraに使われているMySQLやPostgreSQLのように、先進的なエンジンを利用しやすくするフロントエンド的なI/Fとして使われることもなさそうです。

    Amazon Auroraの先進性を誰も解説してくれないから解説する(武蔵野 Advent Calendar 2017 13日目)

    使いどころはやはり手間のかからないオンプレ、と組み込みだと思うので、この観点でまた地道に活動していきたいと思います。十年前から変わってないですが、エバーグリーンということで。

    適材適所のデータベース選択が重要--Firebird日本ユーザー会(ZDNet Japan)

    では、またオープンソースRDBMSの世界で!

    メリークリスマス & ハッピーニューイヤー !!

    JUGEMテーマ:コンピュータ



    | meijik | Firebird/InterBase | 05:23 | comments(0) | trackbacks(0) | - | - |
    古いFirebirdとWindows 10 Fall Creators Update
    0
      本エントリはFirebird Advent Calendar 2017の23日目です。

      ちょっと追いついていませんが、それはおいおい。。。

      さて、首記の件ですが、ちょっと前にメーリングリストで話題になっていて、
      IBPhoenixのドキュメントでもでました。現象は既存のものがアンインストールされ
      再インストールできない、というものです。

      Firebird-jp-general 2017年12月 保存書庫 スレッド

      とりあえずはインストーラ名をSetup.exeに変更することで再度案ストールはできるそうです。

      Firebird and Windows 10 Fall Creators Update(IBPhoenix)

      ご参考まで。

      JUGEMテーマ:コンピュータ



      | meijik | Firebird/InterBase | 13:50 | comments(0) | trackbacks(0) | - | - |
      FirebirdでFLOATを使(う|わない)理由
      0
        FirebirdでFLOATを使(う|わない)理由

        本エントリはFirebird Advent Calendar 2017の22日目です。

        私の本業(=家のローン払いに一番貢献している収入)はMySQLなので、最近以下のエントリを読んでモヤっとしてました。

        MySQLで6桁までの小数点を丸めずに扱うならFLOAT型を使うべき理由(Qiita)

        時間があったらコメントしないとなー、と思ってたら、すでに以下のエントリができてました。多謝。

        MySQLのFLOAT型を使う理由が見つからない件(hnwの日記)

        結論としてMySQLではFLOATがいろんなところで丸まっているので使うべきではないです。
        ではFirebirdはどうか、ということで上記エントリのFirebird版を以下に記述します。

        不思議な挙動(1)...は起こらない。INSERT時に0.9以外になる。

        CREATE TABLE a (f FLOAT, d DOUBLE PRECISION);
        INSERT INTO a VALUES(0.9,0.9);
        SELECT * FROM a;

        F D
        ============== =======================
        0.89999998 0.9000000000000000

        不思議な挙動(2)...も起こらない。f=0.9でもSELECT可能

        SELECT * FROM a WHERE f=0.9;

        F D
        ============== =======================
        0.89999998 0.9000000000000000

        SELECT * FROM a WHERE d=0.9;

        F D
        ============== =======================
        0.89999998 0.9000000000000000

        不思議な挙動(3)...も起こらない。見た数字(INSERTしてSELECTした結果)のとおりの動作です。

        CREATE TABLE b (f1 FLOAT, f2 FLOAT);
        INSERT INTO b VALUES(0.9,0.8999996); -- 8と6の間に9が五個
        INSERT INTO b VALUES(0.9,0.89999996); -- 8と6の間に9が六個

        SELECT * FROM b;

        F1 F2
        ============== ==============
        0.89999998 0.89999962
        0.89999998 0.89999998

        SELECT * FROM b WHERE f1=f2;

        F1 F2
        ============== ==============
        0.89999998 0.89999998

        結果Firebirdでは不思議な挙動はおきないのですが、おきないから、といって積極的に利用をすすめるか、
        といわれると私の答えは"No"ですね。上記ブログのまとめにもありますし、以前私が書いたブログエントリにも記述しましたが、FLOAT型を採用するメリットはサイズが小さいことだけなので、大量に使う場合(==カラムとして複数定義かつ行数が多い場合)の領域削減、時のみ検討すべきで、普通小数を含む場合: 誤差OKならDOUBLE, 誤差NGならNUMERICにすべきです。

        Firebirdで他のRDBMSから来た人に奇妙に見える振る舞いは、計算時の小数点以下の有効範囲の取り扱いでしょうか。
        以下のブログと、そこから参照しているブログ(英語)で、その振る舞いの一端がわかります。

        Firebird のお勉強 計算時の小数点以下の有効範囲(布団が俺を呼んでいる)

        P.S. Firebirdはdoubleではだめでdouble precisionと書かないとエラーです。。。。

        create table c(d double); -- NG
        Statement failed, SQLSTATE = 42000
        Dynamic SQL Error
        -SQL error code = -104
        -Token unknown - line 1, column 24
        -)
        create table c(d double precision); -- OK

        JUGEMテーマ:コンピュータ



        | meijik | Firebird/InterBase | 23:24 | comments(0) | trackbacks(0) | - | - |
        DISTINCT, COUNT, そしてNULL
        0
          本エントリはFirebird Advent Calendar 2017の14日目です。

          DISTINCT, COUNT, そしてNULL

          唐突ですが、次の文章のうち間違っているものは? SELECT文で。。。。

          (1) 行数を数えるときにはCOUNT(*)
          (2) 行数を数えるときにはCOUNT(カラム名)でも(1)と同じ
          (3) カラムのユニークな行数を数えるときはCOUNT(DISTINCT カラム名)
          (4) 複数カラムのユニークな行数を数えるときはCOUNT(DISTINCT カラム名1, カラム名2)

          じゃ確認してみましょう。

          create table t1(i1 int, i2 int);
          insert into t1 values(1,1);
          insert into t1 values(1,2);
          insert into t1 values(2,3);
          select count(*) from t1;

          COUNT
          =====================
          3

          select count(i1) from t1;

          COUNT
          =====================
          3

          (1),(2)ともによさそうに見えますね。。。。ってちょっと待ったー! もう一行nullを含む行を追加してみましょう。

          insert into t1 values(null,3);

          select count(*) from t1;

          COUNT
          =====================
          4

          select count(i1) from t1;

          COUNT
          =====================
          3

          そう、実は集約関数はNULLを除外します。ただし「COUNT(*)」は例外的にNULLを除外しないのです。
          そのため、上記のような違いが現れます。Firebirdに限らず、標準SQLに準拠しているものはすべてそうなります。

          SQLのCOUNT(*)とCOUNT(列名)では結果が異なる(山本隆の開発日誌)

          select count(distinct i1) from t1;

          COUNT
          =====================
          2

          これはまず、distinctで1,2,nullの三行になり、count(列名)はnullを除外するので、2となります。
          これはcountを除いた以下のクエリで一目両全です。(3)はOKそうですね。

          select distinct i1 from t1;

          I1
          ============
          <null>
          1
          2

          次に(4)にトライしてみると。。。。エラーですね。

          select count(distinct i1,i2) from t1;
          Statement failed, SQLSTATE = 42000
          Dynamic SQL Error
          -SQL error code = -104
          -Token unknown - line 1, column 25
          -,

          そう、Firebirdを含めたほとんどのRDBMSではCOUNT(DISTINCT マルチカラム)は許されていないのです。
          そのため、よく代案として利用されるのが、DISTINCTをサブクエリにした以下のクエリや、DISTINCTの代わりにGROUP BYを使うものです。

          select count(*) from (select distinct i1,i2 from t1);

          COUNT
          =====================
          4

          もう一つはカラムを、そのカラムに出てこないデリミタを入れてCONCATするものです。

          select count(distinct i1 || '-' || i2) from t1;

          COUNT
          =====================
          3

          OK, って一行減ってますね。。。。これもcountを除くと意味がわかります。

          select distinct i1 || '-' || i2 from t1;

          CONCATENATION
          =======================
          <null>
          1-1
          1-2
          2-2

          NULLをCONCATするとNULLになり、それはCOUNTに計上されません。そのため巷のDISTINCTをサブクエリに
          する方法は、データにNULLがあると正しくないのです。厳密にいうと、こうなります。

          select count(*) from (select distinct i1,i2 from t1 where i1 is not null and i2 is not null);

          COUNT
          =====================
          3

          本ブログエントリの最初のほうで「ほとんどのRDBMSではCOUNT(DISTINCT マルチカラム)は許されていない」
          と記述しましたが、唯一許されているのがMySQLです。

          create table t1(i1 int, i2 int);
          insert into t1 values(1,1);
          insert into t1 values(1,2);
          insert into t1 values(2,3);
          insert into t1 values(null,3);

          select count(distinct i1,i2) from t1;
          +-----------------------+
          | count(distinct i1,i2) |
          +-----------------------+
          | 3 |
          +-----------------------+
          1 row in set (0.03 sec)

          ということで、正しくでるのですが、DISTINCTしたマルチカラムそれぞれにIS NOT NULLをANDでつけていないクエリで
          NULLを含むデータを投入して「結果が違う〜」という向きがいるので、それはこのような違いがある、ということを
          覚えておいてください!

          結果(1),(3)はOK, (2)は違う(カラムがnot nullならOK), (4) はMySQLだけ、ということになります。

          JUGEMテーマ:コンピュータ



          | meijik | Firebird/InterBase | 19:55 | comments(0) | trackbacks(0) | - | - |
          FirebirdでPostgreSQL(標準SQL?)のCURRENT_TIMESTAMPを模倣
          0
            本エントリはFirebird Advent Calendar 2017の14日目です。

            FirebirdでPostgreSQL(標準SQL?)のCURRENT_TIMESTAMPを模倣


            現在セルコ著、ミックさん翻訳のプログラマのためのSQLを絶賛読書会中(参加者絶賛募集中!)なのですが

            プログラマのためのSQL 読書会(12)

            その「11章時間型」にも記述がありますし、(プログラマのためのSQL第四版(日本語版と英語版からの引用))

            →ここから引用
            タイムスタンプはシステムの時計を一度だけ読み、同一トランザクション内のすべての項目に同じ時間を適用する。
            Remember that a TIMESTAMP will read the system clock once and use that same time on all the items involved in a transaction.
            ←ここまで引用

            去年のFirebird Advent Calendar 2016でとりあげましたが他とは違うPostgreSQL(とVertica)の実装が正しいように見えます。

            使い慣れたSQLに潜む実装依存: Firebirdの場合(5) CURRENT_TIMESTAMP

            今回はその動作をFirebirdで模倣する方法について考えてみました。

            基本的には以下の考えでいけるはずです。

            (1) トランザクションの開始時刻をシステムから取得する。
            (2) (1) をコンテキスト変数に格納する。
            (3) トランザクション内のCURRENT_TIMESTAMPを参照する部分を(2)に置き換える。

            (1)
            トランザクションの開始時刻を知るにはモニタリングテーブルのうち、以下のテーブルを使います。

            MON$TRANSACTION

            現在のトランザクションIDはcurrent_transaction, 現在の接続はcurrent_connectionで取得できますので、
            MON$TRANSACTIONから、トランザクション開始時刻を求めるクエリは以下になります。

            select mon$timestamp from mon$transactions where current_connection = mon$attachment_id and current_transaction=mon$transaction_id;

            MON$TIMESTAMP
            =========================
            2017-12-13 22:56:49.3670

            (2)
            これをユーザコンテキスト変数'CurrentTS'にrdb$set_contextを使って値を設定します。以下のクエリとなります。

            select rdb$set_context('USER_TRANSACTION', 'CurrentTS', (select mon$timestamp from mon$transactions where current_connection = mon$attachment_id and current_transaction=mon$transaction_id)) from rdb$database;

            RDB$SET_CONTEXT
            ===============
            1

            (3)
             (2)で格納した値をrdb$get_contextを使って利用します。
            たとえば以下のようにtimestamp列に現在時刻を挿入していた場合、

            insert into ts1 values(current_timestamp);

            以下のように変更すれば、トランザクション中は、トランザクション開始時刻を設定することが可能です。

            insert into ts1 values((select rdb$get_context('USER_TRANSACTION', 'CurrentTS') from rdb$database));

            JUGEMテーマ:コンピュータ



            | meijik | Firebird/InterBase | 09:05 | comments(0) | trackbacks(0) | - | - |
            Firebird CTEでFizzBuzz
            0
              Firebird CTEでFizzBuzz

              本エントリはFirebird Advent Calendar 2017の13日目です。

              DEKOさんが以下のエントリを書いていたので、それのCTE(Common Table Expression)版を作ってみました。

              Firebird SQL のストアドプロシージャで FizzBuzz(FizzBuzz Advent Calendar 2017)

              WITH RECURSIVE my_cte AS
              (
              SELECT 1 AS i from rdb$database
              UNION ALL
              SELECT 1+i FROM my_cte WHERE i<20
              )
              SELECT CASE
              WHEN (mod(i,3)=0) AND (mod(i,5)=0) THEN 'Fizz Buzz'
              WHEN mod(i,3)=0 THEN 'Fizz'
              WHEN mod(i,5)=0 THEN 'Buzz'
              ELSE i END
              FROM my_cte;

              実行するとこんな感じ。

              CASE
              ==========
              1
              2
              Fizz
              4
              Buzz
              Fizz
              7
              8
              Fizz
              Buzz
              11
              Fizz
              13
              14
              Fizz Buzz
              16
              17
              Fizz
              19
              Buzz

              CTEの再帰クエリで連番を生成し、それを検索CASE式で分岐しています。

              連番の生成の説明は以下をご覧ください。

              MySQL 8.0 Lab版: MySQLの (再帰)共通テーブル式(CTE)(Yakst)

              検索CASE式については以下をご覧ください。

              CASE式のススメ(リレーショナル・データベースの世界)

              JUGEMテーマ:コンピュータ



              | meijik | Firebird/InterBase | 02:17 | comments(0) | trackbacks(0) | - | - |
              Firebirdでカジュアルに再帰クエリでUPDATE/DELETE
              0
                Firebirdでカジュアルに再帰クエリでUPDATE/DELETE

                本エントリはFirebird Advent Calendar 2017の12日目です。

                さて、CTEはOSSのRDBMSの中でも、わりと早い時期(Firebird 2.1)に実装したFirebirdですが、
                最近のCTEのようにUPDATE, DELETE, INSERTなどには対応せず、SELECTのみの対応になります。
                そのFirebirdで、先日紹介したPostgreSQLのようにUPDATEやDELETEをする方法をお知らせします。

                PostgreSQLでカジュアルに再帰クエリ実行with共通表式(CTE:Common Table Expression)

                1.前準備
                UPDATEのためにあらかじめtimestamp列を追加しておきます。

                CREATE TABLE shain(empid INT PRIMARY KEY, name VARCHAR(20), mgrid INTEGER,ts timestamp);
                INSERT INTO shain(empid,name,mgrid) VALUES ( 1, 'みやはら', NULL);
                INSERT INTO shain(empid,name,mgrid) VALUES ( 2, 'きむら', 1);
                INSERT INTO shain(empid,name,mgrid) VALUES ( 3, 'かまたき', 1);
                INSERT INTO shain(empid,name,mgrid) VALUES ( 4, '加藤', 2);
                INSERT INTO shain(empid,name,mgrid) VALUES ( 5, '林', 2);
                INSERT INTO shain(empid,name,mgrid) VALUES ( 6, '三浦', 5);

                UPDATE shain SET mgrid = (SELECT empid FROM shain WHERE name='かまたき') WHERE name = '林';

                2.UPDATE/DELETE

                CTEのSELECTをUPDATE条件の副問い合わせの中にいれてUPDATEです。

                UPDATE shain SET ts = CURRENT_TIMESTAMP WHERE empid IN (
                WITH RECURSIVE n AS
                (
                SELECT empid, name FROM shain WHERE name = 'かまたき'
                UNION ALL
                SELECT nnext.empid, nnext.name FROM shain as nnext, n WHERE n.empid= nnext.mgrid
                )
                SELECT empid FROM n);

                FirebirdではUPDATE ... FROMができないため、結合してのUPDATEはできません。

                Update a table with join?(Stack Overflow)

                DELETEはUPDATEと同様に、以下のとおりです。

                DELETE FROM shain WHERE empid IN (
                WITH RECURSIVE n AS
                (
                SELECT empid, name FROM shain WHERE name = 'かまたき'
                UNION ALL
                SELECT nnext.empid, nnext.name FROM shain as nnext, n WHERE n.empid= nnext.mgrid
                )
                SELECT empid FROM n);

                JUGEMテーマ:コンピュータ



                | meijik | Firebird/InterBase | 06:31 | comments(0) | trackbacks(0) | - | - |
                Firebirdでデータの歯抜けを探す(NULLあり、の続き)
                0
                  Firebirdでデータの歯抜けを探す(NULLあり、の続き)

                  本件はFirebird Advent Calendar 2017の11日目です。

                  一昨日のブログ書いてから気づいたんですが、以下の条件に加えてもうひとつ条件がありました。

                  条件1: seqは整数
                  条件2: seqは1からはじまり、1ずつ増えていく連番
                  条件3: seqはNULLではない。
                  条件4: (seq+1)はオーバーフローしない
                  条件5: seqは重複しない

                  つまり、seqをINTEGERで宣言すると条件1を満たし、さらにUNIQUE制約をつけると条件5、
                  さらにPRIMARY KEYにすれば条件条件3, ダメ押しでMySQLでいう「AUTO_INCREMENT」的な
                  機能をつけると条件4以外を満たすことになります。

                  ただしAUTO_INCREMENTはMySQL特有の機能でFirebirdにはないので

                  3.6.9 AUTO_INCREMENT の使用(MySQL 5.6 日本語マニュアル)

                  Firebirdでは以下のブログやそこから参照している"Firebird Generator Guide"を参考にしてみてください。

                  FirebirdでSEQUENCEを使う。(山本隆の開発日誌)

                  さて、一昨日はWindow関数を使わない解法でしたが、Window関数を使った場合でNULLが含まれているとどうでしょう?
                  表の状態は一昨日の状態(つまり2017-12-08の表に、null行を二行追加したもの)で、2017-12-08の解法をそのまま使うと
                  どうなるでしょうか?

                  select coalesce(max(seq), 0) + 1 as gap
                  from (select seq, Row_Number() over(order by seq) as Rn
                  from SeqTbl) a
                  where seq = Rn;

                  GAP
                  =====================
                  9

                  あれ、正しい4でなく、9が戻りました。2017-12-08のように、副問い合わせの中身だけで確認すると以下のとおりです。

                  select seq, Row_Number() over(order by seq) as Rn from SeqTbl;

                  SEQ RN
                  ============ =====================
                  <null> 1
                  <null> 2
                  1 3
                  2 4
                  3 5
                  5 6
                  6 7
                  8 8 <- たまたま一致した行のmax(seq) + 1で9が戻る

                  これを避けるためには、NULLを省いて、SEQの先頭を1にそろえる必要があります。
                  簡単な方法はorder byにnulls lastを加えて、nullの行をソートした結果の最後においやる方法です。

                  select coalesce(max(seq), 0) + 1 as gap
                  from (select seq, Row_Number() over(order by seq nulls last) as Rn
                  from SeqTbl) a
                  where seq = Rn;

                  GAP
                  =====================
                  4

                  これで無事正しい値が求まりました。Firebirdのnulls lastについては以下のブログ記事をご参照ください。

                  使い慣れたSQLに潜む実装依存: Firebirdの場合(10) ORDER BY でのNULLの扱い

                  JUGEMテーマ:コンピュータ



                  | meijik | Firebird/InterBase | 00:11 | comments(0) | trackbacks(0) | - | - |
                  Firebirdでデータの歯抜けを探す(NULLあり)
                  0
                    本件はFirebird Advent Calendar 2017の9日目です。

                    昨日のブログとそこから参照している記事の当該部分は、以下の条件が(暗黙的に?)あります。

                    条件1: seqは整数
                    条件2: seqは1からはじまり、1ずつ増えていく連番
                    条件3: seqはNULLではない。
                    条件4: (seq+1)はオーバーフローしない

                    そのためミックさんが記事で最後にふれていたように、seqがNULLだとうまく動作しません。
                    前提は昨日のブログで作成したテーブル(SeqTbl)で、そこに一件挿入してみます。

                    insert into seqtbl values(null,null);
                    SELECT '歯抜けあり' AS gap FROM SeqTbl HAVING COUNT(*) <> MAX(seq);

                    GAP
                    ==========
                    歯抜けあり

                    あれ、動作しますね。ではもう一件。

                    insert into seqtbl values(null,null);
                    SELECT '歯抜けあり' AS gap FROM SeqTbl HAVING COUNT(*) <> MAX(seq);

                    あれれ、検知できなくなりました。これはNULL込みの行数が8行(6+2行)になり、MAX(seq)と一緒になってしまったからです。
                    これはcount(*)がnullの行を含んでカウントするからです。nullを含まないでカウントするにはcount(seq)のように直接カラムを指定します。

                    SELECT '歯抜けあり' AS gap FROM SeqTbl HAVING COUNT(seq) <> MAX(seq);

                    GAP
                    ==========
                    歯抜けあり

                    「そもそもNULLあるの?」というのはcount(*)とcount(seq)が違うことでわかります。

                    SELECT 'NULLあり' AS gap FROM SeqTbl HAVING COUNT(*) <> count(seq);

                    GAP
                    ========
                    NULLあり

                    まぁ、ただそれを知るだけなら、以下のクエリのほうが速そうな気がします。

                    select exists(select seq from seqtbl where seq is null) as "nullあり?" from rdb$database;

                    nullあり?
                    =========
                    <true>

                    なお、データにnullがあるとgapの最小値をもとめるこのクエリも当然うごきませんが、

                    SELECT MIN(seq + 1) AS gap FROM SeqTbl WHERE (seq+1) NOT IN ( SELECT seq FROM SeqTbl );

                    GAP
                    =====================
                    <null>

                    動作させるためには、NOT INのサブクエリでnullをはぶく(where seq is not null)だけで大丈夫です。

                    SELECT MIN(seq + 1) AS gap FROM SeqTbl WHERE (seq+1) NOT IN ( SELECT seq FROM SeqTbl where seq is not null);

                    GAP
                    =====================
                    4

                    本日はこんなところで。明日はまたnakagamiさんです!!


                    JUGEMテーマ:コンピュータ



                    | meijik | Firebird/InterBase | 08:04 | comments(0) | trackbacks(0) | - | - |
                    Firebirdの分析関数の衝撃(1)row_numberでデータの歯抜けを探す
                    0
                      MySQLも8.0からWindow関数が実装され、これでオープンソースRDBMS御三家すべてでWindow関数が利用できるようになります。(PostgreSQLは8.4から、Firebirdは3.0から実装済み)

                      今後は各種SQL本でも、Window関数が普通に掲載され、普通に利用されてくると思いますので、
                      ここではミックさんや山岸さんが扱わない(たぶん)Firebirdでの利用について、検証・紹介しておきます。

                      1.データの歯抜けを探す(Window関数を使わない方法)

                      データの歯抜けを探す方法はミックさんの「HAVING句の力(CodeZine)」記事にて説明されています。

                      FirebirdでもWindow関数を持たない3.0より前のバージョンでは、この方法が使えます。以下のテーブルを
                      使って、参照先の方法を試してみてください。

                      create table SeqTbl(seq int, name varchar(10));
                      insert into SeqTbl values(1,'ディック');
                      insert into SeqTbl values(2,'アン');
                      insert into SeqTbl values(3,'ライル');
                      insert into SeqTbl values(5,'カー');
                      insert into SeqTbl values(6,'マリー');
                      insert into SeqTbl values(8,'ベン');
                      commit;

                      2.データの歯抜けを探す(Window関数を使う方法)
                      以下で説明されています。

                      PostgreSQLの分析関数の衝撃1(モードとメジアン)(CodeZine)

                      select coalesce(max(seq), 0) + 1 as gap
                      from (select seq, Row_Number() over(order by seq) as Rn
                      from SeqTbl) a
                      where seq = Rn;

                      これをFirebird 3.0で実行すると、データの歯抜けで一番若い番号、すなわち4が入ります。

                      GAP
                      =====================
                      4

                      動作のイメージがわかない! という人はサブクエリaだけを抜き出して実行するとわかりやすいと思います。
                      (山岸さんの記事の「SQLの処理イメージと考え方」の部分です)

                      select seq, Row_Number() over(order by seq) as Rn from SeqTbl;

                      SEQ RN
                      ============ =====================
                      1 1
                      2 2
                      3 3 <- この行までSEQ = RNなのでmax(seq)はここ、それに1を足すとGAPになる
                      5 4
                      6 5
                      8 6

                      実は参照した山岸さんの記事は二年まえにもざっくり紹介したのですが、今回はもう少し細かくみていくことにします。

                      Firebird 3.0 の Window関数(キムラデービーブログ)

                      JUGEMテーマ:コンピュータ



                      | meijik | Firebird/InterBase | 06:07 | comments(0) | trackbacks(0) | - | - |
                            1
                      2345678
                      9101112131415
                      16171819202122
                      23242526272829
                      30      
                      << September 2018 >>
                      + 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