キムラデービーブログ

オープンソースデータベースを加速する「キムラデービー」のブログです。カレー日記を兼ねてます。なお著者は2010-06-01より日本オラクルに在籍していますが、本サイト(ブログ、またはウェブサイト)において示されている見解は、私自身の見解であって、オラクルの見解を必ずしも反映したものではありません。
<< プログラマのためのSQL第四版読書会(12)11.時間型 (p.225) | main | FirebirdでFLOATを使(う|わない)理由 >>
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) | - | - |









    http://blog.kimuradb.com/trackback/877520
          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