キムラデービーブログ

オープンソースデータベースを加速する「キムラデービー」のブログです。カレー日記を兼ねてます。なお著者は2010-06-01より日本オラクルに在籍していますが、本サイト(ブログ、またはウェブサイト)において示されている見解は、私自身の見解であって、オラクルの見解を必ずしも反映したものではありません。
<< Windows上で、SQLiteのGeopolyを使う(ということはMSVCでコンパイルするのねん) | main | Firebirdの分析関数の衝撃(13) 関係除算を表現する >>
Firebirdの分析関数の衝撃(12) 2つのテーブルが相等であるかどうか
0
    Firebirdの分析関数の衝撃(12) 2つのテーブルが相等であるかどうか

    本エントリはFirebird Advent Calendar 2018 18日目のエントリです。

    1. 2つのテーブルが相等なら「等しい」、そうでなければ「異なる」を返すクエリ

    INTERSECTとEXCEPTがないFirebird(とMySQL)にとっては、この書き換えは迷宮のようなわけのわからなさになることうけあいです。そのため、以下のように一番短い(そのように見える)以下のクエリを題材にしましょう。

    -- window関数で書き換えたSQL
    select case when count(*) = 0
    then '等しい'
    else '異なる' end as result
    from (select count(*) over(),* from tbl_A
    except all
    select count(*) over(),* from tbl_B) a;

    [Firebird版の完成系はこちら]
    -- CTEに複数の定義を書いて、そのサブクエリ化
    select case when count(*) = 0
    then '等しい'
    else '異なる' end as result
    from
    (
    -- S1 EXCEPT ALL S2(Firebird with CTEバージョン)
    WITH RECURSIVE Series AS
    (
    SELECT 1 AS seq from rdb$database
    UNION ALL
    SELECT 1+seq FROM Series where seq < 8
    ),
    S1 AS (select count(*) over() c, tbl_A.* from tbl_A),
    S2 AS (select count(*) over() c, tbl_B.* from tbl_B)
    SELECT D2.a
    FROM (SELECT D1.a, SUM(cnt)
    FROM (SELECT a1, COUNT(*)
    FROM S1
    GROUP BY a1
    UNION ALL
    SELECT a2, -COUNT(*)
    FROM S2
    GROUP BY a2) AS D1(a, cnt)
    GROUP BY D1.a
    HAVING SUM(cnt) > 0) AS D2(a, dups)
    INNER JOIN
    Series ON seq <= D2.dups
    ) a;

    元のクエリとは当然大きく異なるのですが、Firebird版では以下の変更が必要です。
    (1) count(*) over()にカラム名が必要。ここではcとした。つけないと以下のエラー
    Statement failed, SQLSTATE = 42000
    Dynamic SQL Error
    -SQL error code = -104
    -Invalid command
    -no column name specified for column number 1 in derived table S1
    (2) (1)に続く*ではエラー。テーフル名.*の表記が必要。

    なお、MySQL版では(1)は不要ですがオリジナルのクエリと比較して(2)と以下(3)が必要。
    (3) テーブルの別名にASが必要。すなわちクエリの最後が) as a;である必要があり。

    また

    (4) SELECT 1 AS seq from rdb$databaseのfrom以下が不要、なのはご存知のとおり。

    以下、[MySQL版]のクエリを組み立てながら説明します。

    "except all"については、先日のブログでとりあげましたよね。
    select count(*) over(),* from tbl_AにS1という名称をつけて、
    select count(*) over(),* from tbl_BにS2という名称をつけて、
    fromの中を(S1 except all S2)という形にすると、先日のブログと同じように処理できそうです。

    さて、どうやって名前をつけましょうか? 実はCTEはカンマで繋いで、複数定義できます!

    with — Organize Complex Queries

    なので、以下のようにexcept allを表現できます。

    -- S1 EXCEPT ALL S2(MySQL with CTEバージョン)
    WITH RECURSIVE Series AS
    (
    SELECT 1 AS seq -- from rdb$database
    UNION ALL
    SELECT 1+seq FROM Series where seq < 8
    ),
    S1 AS (select count(*) over(), tbl_A.* from tbl_A),
    S2 AS (select count(*) over(), tbl_B.* from tbl_B)

    SELECT D2.a
    FROM (SELECT D1.a, SUM(cnt)
    FROM (SELECT a1, COUNT(*)
    FROM S1
    GROUP BY a1
    UNION ALL
    SELECT a2, -COUNT(*)
    FROM S2
    GROUP BY a2) AS D1(a, cnt)
    GROUP BY D1.a
    HAVING SUM(cnt) > 0) AS D2(a, dups)
    INNER JOIN
    Series ON seq <= D2.dups;

    これに使うtbl_A, tbl_Bを用意します。keyをa1,a2に変更して、同一のテーブルを生成します。

    create table tbl_A(
    a1 char(1) not null primary key,
    col_1 int,
    col_2 int,
    col_3 int);

    insert into tbl_A values('A',2,3,4);
    insert into tbl_A values('B',0,7,9);
    insert into tbl_A values('C',5,1,6);

    create table tbl_B(
    a2 char(1) not null primary key,
    col_1 int,
    col_2 int,
    col_3 int);

    insert into tbl_B select * from tbl_A;
    commit;

    これでCTEの戻り値はEmptyです。(tbl_A, tbl_Bは同一)

    元のクエリが(S1 except all S2)をサブクエリにしていたので、同様に上のCTEもサブクエリにしてみます。

    [MySQL版の完成系はこちら]
    -- CTEに複数の定義を書いて、そのサブクエリ化
    select case when count(*) = 0
    then '等しい'
    else '異なる' end as result
    from
    (
    -- S1 EXCEPT ALL S2(MySQL with CTEバージョン)
    WITH RECURSIVE Series AS
    (
    SELECT 1 AS seq -- from rdb$database
    UNION ALL
    SELECT 1+seq FROM Series where seq < 8
    ),
    S1 AS (select count(*) over(), tbl_A.* from tbl_A),
    S2 AS (select count(*) over(), tbl_B.* from tbl_B)
    SELECT D2.a
    FROM (SELECT D1.a, SUM(cnt)
    FROM (SELECT a1, COUNT(*)
    FROM S1
    GROUP BY a1
    UNION ALL
    SELECT a2, -COUNT(*)
    FROM S2
    GROUP BY a2) AS D1(a, cnt)
    GROUP BY D1.a
    HAVING SUM(cnt) > 0) AS D2(a, dups)
    INNER JOIN
    Series ON seq <= D2.dups
    ) as a;

    +-----------+
    | result |
    +-----------+
    | 等しい |
    +-----------+
    1 row in set (0.00 sec)

    一行増やして
    insert into tbl_A values('X',1,2,3); commit;

    再実行すると、この結果
    +-----------+
    | result |
    +-----------+
    | 異なる |
    +-----------+
    1 row in set (0.00 sec)

    JUGEMテーマ:コンピュータ



    | meijik | Firebird/InterBase | 00:43 | comments(0) | trackbacks(0) | - | - |









    http://blog.kimuradb.com/trackback/877561
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    << March 2019 >>
    + 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
    • 毎月日経SYSTEMSが届くたびに?が増え続ける: 日経SYSTEMSのコラム「ITアーキテクチャーの真髄」と「第7正規化」
      meijik (03/03)
    • 2019年の木村明治
      田中尚 (01/08)
    • 使い慣れた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)
    + RECENT TRACKBACK
    + CATEGORIES
    + ARCHIVES
    + MOBILE
    qrcode
    + LINKS
    + PROFILE