21

我希望在 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 = ?

我希望通过默认的 Contacts ContentProvider 选择系统通讯录中所有联系人的 ID 和名称,以及指示联系人是否是 group 成员的 0/1 字段?

我当然可以很容易地获得所有联系人,然后在我的 Adapter 类中很容易地循环并分别查询成员资格,但我想将这两个查询作为一个外部连接查询执行会产生更好的性能。

我可以使用标准的高级字符串投影和ContentResolver.query()方法来做到这一点吗?或者这种查询是否需要深入研究更直接的 SQL 执行?

4

3 回答 3

42

编辑: 好的,所以这实际上并不能解决所提出的问题,因为 eidylon 与他们的问题中提到的现有 ContentProvider 相关联。但是,如果您拥有 ContentProvider 源和 API,这确实涵盖了如何执行 JOIN。所以我会把它留给那些想知道如何处理这种情况的人。


这很简单!但是不直观... :)

query(Uri uri, String[] projection, String selection, 
String[] selectionArgs, String sortOrder)

好的,那么 URI 是什么?通常,每个表都有一个 URI。

content://com.example.coolapp.contactsCONTACTS从您的表中 提供数据。从您的表中content://com.example.coolapp.groupmembers提供数据。GROUPMEMBERSHIP

但 URI 实际上只是一个字符串。随心所欲地使用它。在您的 ContentProvider 中创建一个响应content://com.example.coolapp.contacts_in_group. 在 ContentProvider 中的代码块中,您可以获得对 SQLite DB 的原始访问权限,而不受有限query()数据模型的限制。随意使用它!

随意定义您的选择字段。它们不必映射到表列名称——按照您的需要映射它们,以便获取您的参数。

定义您需要的投影——它可能包含连接后两个表中的列。

宾,你完成了。谷歌在他们自己的代码中内部使用了同样的模型——去看看联系人提供者 API——你会看到“bla.RawContact”和“bla.Contact”等作为内容 URI。每个都从数据库中的同一张表中提供数据——不同的 URI 只是提供同一张表的不同视图

于 2011-07-01T13:41:01.690 回答
8

不,您不能使用该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);
于 2011-06-27T13:08:43.727 回答
0

你不能这样做,因为 ContentResolver 只有一种查询方法:

    query(Uri uri, String[] projection, String selection, 
String[] selectionArgs, String sortOrder)

表或 FROM 子句没有参数。

于 2011-06-30T09:08:26.197 回答