19

Busco para realizar la siguiente consulta (en pseudo-código) en Android:¿Puedo realizar esta consulta de Android con ContentResolver.query()? (LEFT JOIN y CASE)

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 = ? 

Busco para seleccionar el identificador y el nombre de todos los contactos en la libreta de direcciones del sistema, a través de los Contactos predeterminados ContentProvider, junto con un campo 0/1 que indica si el contacto es miembro del grupo ?.

Pude, por supuesto, obtener todos los contactos con bastante facilidad, luego recorrer y consultar la membresía por separado de manera sencilla en mi clase de Adaptador, pero me imagino que realizar las dos consultas como una consulta externa generaría un rendimiento mucho mejor.

¿Puedo hacer esto con el método estándar de proyección de cuerdas de alto nivel y el método ContentResolver.query()? ¿O este tipo de consulta requeriría profundizar en una ejecución SQL más directa?

Respuesta

7

No, no puede hacer ese tipo de consultas con el método ContentResolver.query(). Usted tendrá que escribir algo como esto:

SQLiteDatabase db = YourActivity.getDbHelper().getReadableDatabase(); 
String query = yourLongQuery; 
Cursor c = db.rawQuery(query, null); 
YourActivity.startManagingCursor(c); 
c.setNotificationUri(YourActivity.getContentResolver(), YourContentProvider.CONTENT_URI); 
+0

Al buscar, me da la impresión de que no puede usar SQLLiteDatabase para consultar otras aplicaciones ... en mi caso, el URL de CONTACTS, pero solo para consultar sus propios almacenes de datos. ¿Es esto correcto? En cuyo caso, supongo que me quedaría bloqueado la realización de subconsultas en mi clase de Adaptador al vincular mi actividad. – eidylon

+0

@eidylon: No sabía que estabas consultando los Contactos db. Sí, tienes razón :( – Macarse

+0

Drat! Oh bien ... en adelante y en adelante! Gracias! – eidylon

0

No se puede hacer eso porque ContentResolver tiene sólo un método de consulta:

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

no hay parámetros para las tablas o las cláusulas FROM.

41

Edit:Bueno, esto no soluciona realmente la pregunta, porque eidylon está vinculado a un ContentProvider existente como se menciona en su pregunta. Sin embargo, esto cubre cómo realizar un JOIN si posee el origen y API de ContentProvider. Así que lo dejo para aquellos que quieran saber cómo manejar ese caso.


¡Esto es fácil! Pero poco intuitivo ... :)

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

Bien, entonces ¿qué es URI? Normalmente, tienes un URI por mesa.

content://com.example.coolapp.contacts sirve datos de su tabla CONTACTS. content://com.example.coolapp.groupmembers sirve datos de su tabla GROUPMEMBERSHIP.

Pero URI es solo una cadena. Úselo como lo desee. Haga un bloque de código en su ContentProvider que responda al content://com.example.coolapp.contacts_in_group. Dentro de ese bloque de código en ContentProvider, puede obtener acceso sin formato a su base de datos SQLite, sin restricciones por el modelo de datos query() limitado. ¡Sientase libre de usarlo!

Defina sus campos de selección como prefiera. Ellos no tienen para asignar a los nombres de columna de la tabla - Mapa de cómo es necesario, con el fin de obtener sus parámetros de

Definir su proyección de la forma en que necesita -. Puede contener columnas de ambas tablas después la unión

Bing, listo. Google hace este mismo modelo internamente en su propio código. Ve a la API del proveedor de contactos: ves "bla.RawContact" y "bla.Contact" y etc. como URI de contenido.Cada uno de ellos sirve datos de la misma tabla en la base de datos. ¡Los diferentes URI solo proporcionan diferentes vistas de esa misma tabla!

+0

Gracias por la respuesta ... es muy detallada e informativa, así que subí de categoría, pero aparentemente *** era I *** que no estaba claro en mi Q que estaba consultando los Contactos de Android db, no los de mi propio DB. Usted no fue el único que se perdió esto. He actualizado mi redacción para ser un poco más claro al respecto. ¡Gracias! :) – eidylon

+1

Lo siento, sí. Si está usando un contactProvider existente, está atrapado con los URI de contenido y las combinaciones que implementaron. – jcwenger

+0

para resumir esto, en su proveedor de contenido, anule el método de "consulta", verifique su URI y haga lo que desee con una conexión directa a su base de datos SQLite. ¡Gracias! –