Могу ли я выполнить этот запрос Android с помощью ContentResolver.query()? (ЛЕВОЕ СОЕДИНЕНИЕ и ДЕЛО)

Я хочу выполнить следующий запрос (в псевдокоде) на 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 = ?

Я хочу выбрать идентификатор и имя ВСЕХ контактов в адресной книге системы через ContentProvider по умолчанию, а также поле 0/1, указывающее, является ли контакт членом группы ? .

Я мог бы, конечно, достаточно легко получить все контакты, а затем выполнить цикл и запросить членство по отдельности достаточно легко в моем классе адаптера, но я полагаю, что выполнение двух запросов, поскольку один внешний объединенный запрос даст гораздо лучшую производительность.

Могу ли я сделать это с помощью стандартной высокоуровневой проекции строк и метода ContentResolver.query()? Или такой запрос потребует более прямого выполнения SQL?


person eidylon    schedule 14.06.2011    source источник


Ответы (3)


Нет, вы не можете выполнять такие запросы с помощью метода 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);
person Macarse    schedule 27.06.2011
comment
Из поиска у меня сложилось впечатление, что вы не можете использовать SQLLiteDatabase для запросов к другим приложениям... в моем случае CONTACTS uri, но только для запросов к вашим собственным хранилищам данных. Это правильно? В этом случае я думаю, что застрял бы с выполнением подзапросов в моем классе адаптера при привязке моей активности. - person eidylon; 27.06.2011
comment
@eidylon: я не знал, что вы запрашиваете базу данных контактов. Ага, ты прав :( - person Macarse; 27.06.2011
comment
Черт! Ну... вперед и вверх! Спасибо! - person eidylon; 28.06.2011
comment
Суть в том, что нужно быть THE поставщиком контента и определить специальный URI, который затем будет строить запрос специально для сложности. Правильно? @ediyon - я думаю, вы можете принять ответ Макарса. - person mobibob; 30.06.2011

Редактировать: Хорошо, так что на самом деле это не решает заданный вопрос, потому что eidylon привязан к существующему ContentProvider, как указано в их вопросе. Однако это касается того, как вы выполняете JOIN, если у вас есть источник ContentProvider и API. Так что я оставлю это для тех, кто хочет знать, как поступить в этом случае.


Это легко! Но неинтуитивно... :)

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

Итак, что такое URI? Как правило, у вас есть один URI на таблицу.

content://com.example.coolapp.contacts обслуживает данные из вашей CONTACTS таблицы. content://com.example.coolapp.groupmembers обслуживает данные из вашей GROUPMEMBERSHIP таблицы.

Но URI на самом деле просто строка. Используйте его, как вам нравится. Создайте блок кода в вашем ContentProvider, который отвечает на content://com.example.coolapp.contacts_in_group. В этом блоке кода в ContentProvider вы можете получить необработанный доступ к вашей базе данных SQLite, не ограниченный ограниченной моделью данных query(). Не стесняйтесь использовать его!

Определите поля выбора, как вам нравится. Они не должны сопоставляться с именами столбцов таблицы — сопоставляйте их так, как вам нужно, чтобы получить ваши параметры.

Определите свою проекцию так, как вам нужно -- она ​​может содержать столбцы из обеих таблиц после соединения.

Бинг, все готово. Google использует ту же модель внутри своего собственного кода. Посмотрите на API поставщика контактов — вы видите «bla.RawContact», «bla.Contact» и т. д. в качестве URI контента. Каждый обслуживает данные из одной и той же таблицы в БД — разные URI просто обеспечивают разные представления одной и той же таблицы!

person jcwenger    schedule 01.07.2011
comment
Спасибо за ответ ... он очень подробный и информативный, поэтому я проголосовал; но, по-видимому, именно я не понял в своем вопросе, что я запрашивал базу данных контактов Android, а не мою собственную базу данных. Вы были не единственным, кто пропустил это. Я обновил свою формулировку, чтобы немного прояснить это. Спасибо! :) - person eidylon; 03.07.2011
comment
Извините, да. Если вы используете существующий контактный поставщик, вы застряли с любыми URI контента и объединениями, которые они реализовали. - person jcwenger; 10.02.2012
comment
Итак, чтобы подвести итог, в вашем ContentProvider переопределите метод запроса, проверьте свой URI и сделайте все, что хотите, с прямым подключением к вашей базе данных SQLite? Благодарность! - person Brad Parks; 11.05.2013
comment
@jcwenger Не могли бы вы привести пример кода использования внутреннего соединения в contentResolver? - person android developer; 23.01.2014
comment
@jcwenger Пожалуйста, как вы думаете, вы могли бы помочь с этим stackoverflow.com/questions/27257416/? - person eddy; 03.12.2014

Вы не можете этого сделать, потому что ContentResolver имеет только один метод запроса:

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

нет параметра для таблиц или предложений FROM.

person West_Link    schedule 30.06.2011