情報科学屋さんを目指す人のメモ(FC2ブログ版)

何かのやり方や、問題の解決方法をどんどんメモするブログ。そんな大学院生の活動「キャッシュ」に誰かがヒットしてくれることを祈って。

ブログ内検索

スポンサーサイト このエントリーを含むはてなブックマーク

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

スポンサー広告 | 編集
このエントリーをはてなブックマークに追加 Clip to Evernote

データベースから度数分布表を作る このエントリーを含むはてなブックマーク

SQLite データベースから、C#/.NETからSQLを利用して度数分布表を作成する方法について考えます。

環境

C#(.NET)において、System.Data.SQLiteを利用してSQLiteデータベースを構築済み。SQLiteでなくても、リレーショナルデータベースなら、基本は同じはず

目標

度数分布表とは、成績を扱うデータなら、0-9点が5人、10-19点が14人、20-29点が20人…という情報を表にまとめたものです。

その度数分布表の元となる配列(どの範囲に、いくつのデータがあるか)を、作成済みのデータベース(テーブル)から、SQLを用いて作成する。また、利用言語はC#

対象データベース

コードを掲載する前に、対象となるデータベースを紹介します。

  • データベース名:"seiseki.db"
  • テーブル名:"test1"
  • テーブルのスキーマ(属性):
    • NAME CHAR(20)
    • TENSUU INTEGER
  • 行(エンティティ)の例:TANAKA | 60

方法

では、まず度数分布を求めるためのコードを掲載します。

// 度数分布表の区切りを表す配列 boundary
int[] boundary = new int[] { 10, 20, 30, 40, 50, 60, 70, 80, 90 };

// ある区切りまでの累積(10以下、20以下…)数を記録する配列 cumulative
int[] cumulative = new int[boundary.Length + 1];

// 求めたい度数分布の配列 frequency
int[] frequency = new int[boundary.Length + 1];

// 以下、SQLを利用したDBへのアクセス
using (SQLiteConnection cnn = new SQLiteConnection("Data Source=seiseki.db"))
using (SQLiteCommand cmd = cnn.CreateCommand())
{
    cnn.Open();

    // 各区切り値までの累積数を求める
    for (int i = 0; i < boundary.Length; i++)
    {
        cmd.CommandText =
            "SELECT COUNT(*)" +
            "FROM test1" +
            "WHERE TENSUU <= " + boundary[i];
        object o = cmd.ExecuteScalar();
        cumulative[i] = int.Parse(o.ToString());
    }

    // 行数(= 累積数の最後)を求める
    cmd.CommandText =
        "SELECT COUNT(*)" +
        "FROM test1";
    object o = cmd.ExecuteScalar();
    cumulative[cumulative.Length - 1] = int.Parse(o.ToString());

    // 累積数から、度数分布を求める
    frequency[0] = cumulative[0]; // 1つ目は、度数分布と累積数が一緒
    for (int i = 1; i < frequency.Length; i++)
    {
        // 累積数の差から、度数分布を求める
        frequency[i] = cumulative[i] - cumulative[i-1];
    }
}

return frequency;

以上のようにすることで、度数分布表を表すfrequency配列が取得できます。

ポイントとしては、

  1. COUNT関数
  2. ExecuteScalarメソッドの返値をどのように扱うか
の2点が挙げられます。

COUNT関数 は、WHERE以下の条件を満たす行(エンティティ)がいくつあるかを数えてくれる関数です。

ExecuteScalar()を実行すると、COUNT関数が実行され、その結果が返ってきます。

ExecuteScalarのmsdn(System.Data.SQLiteではなく、System.Data.OleDbの)を見てみると、C#でのコード例として、

CommandText = "select count(*) from region";
Int32 count = (int32) EsecuteScalar();
というコードが掲載されていますが、実際にこのようにやってみると、ExecuteScalar関数の結果をキャストすることができませんでした。ちなみに、System.Data.SQLiteのヘルプは詳しくないので使い物になりません

そこで、ほかのキャストも試してみましたが、どうもうまくいきません。結局うまくいったのは上記の通り、まず、ToStringメソッドで文字列に変換し、その文字列をint.Parseメソッドで、int型に変換という方法です。今回の一番のポイントは、これです。

まとめ

以上のようにすることで、度数分布がデータベースから取得できます。もっと効率のよい方法がいくらでもありそうですが、とりあえずこれでうまくできたのでメモしておきました。あくまで参考なので、状況に応じて、改変してください。

訂正ログ

20010/04/10 o.String() の「()」が抜けていた部分を修正。(fx993さんの指摘により修正)

SQLite入門
プログラマのためのSQL
現場で使えるSQL
基礎からのMySQL

データベース | コメント:2 | トラックバック:0 | 編集
このエントリーをはてなブックマークに追加 Clip to Evernote

この記事のコメント

まさに同じ部分で悩んでいてたどり着きました。

int.Parse(o.ToString);

一旦文字に変換してが(o.ToString());と括弧がぬけているような気がしましたが...
私の勘違いならゴメンナサイ。
2010-04-10 Sat 02:59 |  fx993 [ 編集]
fx993さん、コメントありがとうございます!

> まさに同じ部分で悩んでいてたどり着きました。
私のblogを参考にしてもらえたようでうれしいです。

> int.Parse(o.ToString);
>
> 一旦文字に変換してが(o.ToString());と括弧がぬけているような気がしましたが...
> 私の勘違いならゴメンナサイ。
たしかに括弧が抜けていますね。コーディング中もよく忘れるので、同様のミスだと思います。修正しておきました。ありがとうございました。
2010-04-10 Sat 11:24 |  did2

コメントの投稿 エントリの新旧に関わらず、極力18時間中に返信します。














この記事のトラックバック

トラックバックURL:
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。