そごうソフトウェア研究所

SOA、開発プロセス、ITアーキテクチャなどについて書いています。Twitterやってます@rsogo

アプリ内での複数テーブルへの問い合わせ

本エントリでは、Androidアプリで複数のテーブルを結合して情報を取り出すことについて書こうと思います。

AndroidではデータベースとしてSQLiteが用意されています。
業務系のアプリを作るような場合は特にデータの生成、管理がメインの処理になる傾向があるので、SQLiteを使うことも多いと思います。


そこで、テーブルの設計をやることになりますが、正規化を進めていくうちに画面に表示したい項目が複数のテーブルにまたがることも良くあります。


自分の場合、Androidアプリで曖昧な検索を複数テーブルに対して行うことはあまりありません。曖昧な検索とは、社員テーブルに佐藤さんを条件で、売上テーブルに売上100万円以上を条件で両方にヒットしたものを画面に表示するようなものです。理由はおそらく2つ。

1つは、スマホは画面が小さいのでその画面で検索結果が大量にあってページ送りを何度もしないとデータが見れないような画面設計をやらない。これはタブレットになってくるとそんな要件の画面もでてくるのかも知れません。

2つ目は、複数のテーブルの曖昧検索をしたいような場合ってほとんどが分析や一覧用途だと思います。分析したくなるほどのデータががAndroid端末のストレージに蓄積されていることって少ないんじゃないでしょうか。そのような場合、おそらくバックエンドのサービスにデータは蓄積されていて、分析したい場合はバックエンドに問い合わせるでしょう。


複数テーブルに問い合わせるケースで良くあるのが、社員マスタに社員番号と、社員名があり、売上テーブルかには社員番号と社員毎の売上があるような場合です。売上の上位5件を表示したときに社員番号だけではなく社員名も表示したいですよね。


そのような時、社員マスタと売上テーブルを結合してデータを取ってきたくなりますが、どうやってますか?
1つはSQLiteDatabase.rawQuery()を使って、自分でSELECT文を書いてしまうやり方です。これはSQLを書けるので、自由になんでも書けます。

もう一つはSQLiteDatabase.query()を使うやり方ですが、引数にテーブル名を渡す際に、カンマ区切りで複数のテーブルを指定し、Selection(SQLのWhere句に該当)の引数にテーブルを結合するための条件を書けます。すごい端折って書くとこんな感じです。


ContentProviderを呼び出してる方

String[] columns = new String[3];
columns[0] = "RevenueTable.EmpNo";
columns[1] = "EmploeeTable.EmpName";
columns[2] = "RevenueTable.Revenue";

String selection =  "EmploeeTable.EmpNo=RevenueTable.EmpNo";
				
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(uri,  columns, selection, null, null);


ContentProvider側

public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs,String order) {

	Cursor cursor = db.query(
			 "RevenueTable, EmploeeTable",
			projection,
			where,
			whereArgs,
			null, null, order);
	return cursor;
}

参考にさせていただいた記事
Androidアプリのデータ保存方法の一つ「SQLite」の使い方 レコード検索編

Best way to join tables using sqlite in android

SQLiteで外部キー制約

http://stackoverflow.com/questions/2421189/version-of-sqlite-used-in-android