Androidで次のクエリ(擬似コード)を実行しようとしています。
_SELECT C.ID, C.NAME, CASE ISNULL(G.GROUPID,0) = 0 THEN 0 ELSE 1 END INGROUP
FROM CONTACTS C
LEFT JOIN GROUPMEMBERSHIP G ON G.CONTACTID = C.ID AND G.GROUPID = ?
_
連絡先がグループ_?
_のメンバーであるかどうかを示す0/1フィールドとともに、デフォルトの連絡先ContentProviderを介して、システムアドレス帳のすべての連絡先のIDと名前を選択しようとしています。
もちろん、すべての連絡先を簡単に取得してから、Adapterクラスでメンバーシップをループして個別にクエリするのも簡単ですが、1つの外部結合クエリを使用すると、パフォーマンスが大幅に向上するため、2つのクエリを実行すると思います。
標準の高レベル文字列射影とContentResolver.query()
メソッドでこれを行うことはできますか?それとも、この種のクエリでは、より直接的なSQL実行を掘り下げる必要がありますか?
いいえ、ContentResolver.query()
メソッドを使用してそのようなクエリを実行することはできません。次のように書く必要があります。
SQLiteDatabase db = YourActivity.getDbHelper().getReadableDatabase();
String query = yourLongQuery;
Cursor c = db.rawQuery(query, null);
YourActivity.startManagingCursor(c);
c.setNotificationUri(YourActivity.getContentResolver(), YourContentProvider.CONTENT_URI);
編集:わかりました。質問で述べたように、eidylonは既存のContentProviderに関連付けられているため、これでは実際には質問は解決されません。ただし、これは、ContentProviderソースとAPIを所有している場合のJOINの実行方法をカバーしています。だから、その場合の扱い方を知りたい人には任せておきます。
これは簡単!しかし、直感的ではありません... :)
_query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
_
さて、URIとは何ですか?通常、テーブルごとに1つのURIがあります。
_content://com.example.coolapp.contacts
_は、CONTACTS
テーブルからデータを提供します。 _content://com.example.coolapp.groupmembers
_は、GROUPMEMBERSHIP
テーブルからデータを提供します。
しかし、URIは実際には単なる文字列です。好きなように使ってください。 _content://com.example.coolapp.contacts_in_group
_に応答するコードのブロックをContentProviderに作成します。 ContentProviderのコードブロック内で、制限されたquery()
データモデルに縛られることなく、SQLiteDBへの生のアクセスを取得できます。お気軽にご利用ください!
選択フィールドを好きなように定義します。テーブルの列名にマップする必要はありません-パラメータを取得するために必要な方法でマップします。
必要に応じてプロジェクションを定義します-結合後に両方のテーブルの列が含まれる場合があります。
ビンビン、あなたは終わりました。 Googleは、これと同じモデルを独自のコードで内部的に実行しています。連絡先プロバイダーAPIを見てください。コンテンツURIとして「bla.RawContact」や「bla.Contact」などが表示されます。それぞれがDB内の同じテーブルからデータを提供します-異なるURIは、同じテーブルの異なるビューを提供するだけです!
ContentResolverにはクエリメソッドが1つしかないため、これを行うことはできません。
query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
テーブルまたはFROM句のパラメータはありません。