Question

Quelle serait une façon raisonnable d'ajouter DISTINCT et / ou GROUPBY à ContentResolver- requêtes basées. En ce moment, je dois créer URI personnalisés pour chaque cas particulier. Y at-il une meilleure façon? (Je programme encore 1,5 comme dénominateur commun le plus bas)

Était-ce utile?

La solution 2

Puisque personne ne vint à répondre, je vais juste dire comment je résolu ce problème. Fondamentalement, je créerais URI personnalisé pour chaque cas et répondre aux critères dans le paramètre selection. Ensuite, à l'intérieur ContentProvider#query Je décrirais le cas et construire requête brute basée sur le nom de la table et le paramètre de sélection.

Voici par exemple rapide:

switch (URI_MATCHER.match(uri)) {
    case TYPES:
        table = TYPES_TABLE;
        break;
    case TYPES_DISTINCT:
        return db.rawQuery("SELECT DISTINCT type FROM types", null);
    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
    return db.query(table, null, selection, selectionArgs, null, null, null);

Autres conseils

Vous pouvez faire belle entaille lors de l'interrogation ContentResolver, utilisez:

String selection = Models.SOMETHING + "=" + something + ") GROUP BY (" + Models.TYPE;

Si vous souhaitez utiliser avec SELECT DISTINCT plus d'une colonne, vous devez utiliser GROUP BY.
Mini Hack sur ContentResolver.query pour ceci:

Uri uri = Uri.parse("content://sms/inbox");
        Cursor c = getContentResolver().query(uri, 
            new String[]{"DISTINCT address","body"}, //DISTINCT
            "address IS NOT NULL) GROUP BY (address", //GROUP BY
            null, null);
        if(c.moveToFirst()){
            do{
                Log.v("from", "\""+c.getString(c.getColumnIndex("address"))+"\"");
                Log.v("text", "\""+c.getString(c.getColumnIndex("body"))+"\"");

            } while(c.moveToNext());
        }

Ce code sélectionnez un dernier sms pour chacun des expéditeurs de la boîte de réception de l'appareil.
Note: avant GROUP BY nous avons toujours besoin d'écrire au moins une condition. Résultat chaîne de requête SQL dans la méthode ContentResolver.query sera:

SELECT DISTINCT address, body FROM sms WHERE (type=1) AND (address IS NOT NULL) GROUP BY (address) 

Dans votre méthode surchargée de requête ContentProvider un mappage URI spécifiques à l'utilisation distincte.

Utilisez ensuite SQLiteQueryBuilder et appeler la méthode setDistinct(boolean).

@Override
public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder)
{
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

    boolean useDistinct = false;

    switch (sUriMatcher.match(uri))
    {
    case YOUR_URI_DISTINCT:
        useDistinct = true;
    case YOUR_URI:
        qb.setTables(YOUR_TABLE_NAME);
        qb.setProjectionMap(sYourProjectionMap);
        break;

    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    // If no sort order is specified use the default
    String orderBy;
    if (TextUtils.isEmpty(sortOrder))
    {
        orderBy = DEFAULT_SORT_ORDER;
    }
    else
    {
        orderBy = sortOrder;
    }
    // Get the database and run the query
    SQLiteDatabase db = mDBHelper.getReadableDatabase();
            // THIS IS THE IMPORTANT PART!
    qb.setDistinct(useDistinct);
    Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);

    if (c != null)
    {
        // Tell the cursor what uri to watch, so it knows when its source data changes
        c.setNotificationUri(getContext().getContentResolver(), uri);
    }

    return c;
}

Bien que je ne l'ai pas utilisé Grouper par , j'ai utilisé Distinct dans la requête résolveur contenu.

Cursor cursor = contentResolver .query(YOUR_URI, new String[] {"Distinct "+ YOUR_COLUMN_NAME}, null, null, null);

Dans certaines conditions, on peut utiliser « distincte (COLUMN_NAME) » comme la sélection, et il fonctionne parfaitement. mais dans certaines conditions, il fera une exception.

quand il provoque une exception, je vais utiliser un HashSet pour stocker les valeurs de la colonne ....

// getting sender list from messages into spinner View
    Spinner phoneListView = (Spinner) findViewById(R.id.phone_list);
    Uri uri = Uri.parse("content://sms/inbox");     
    Cursor c = getContentResolver().query(uri, new String[]{"Distinct address"}, null, null, null);
    List <String> list;
    list= new ArrayList<String>();
    list.clear();
    int msgCount=c.getCount();
    if(c.moveToFirst()) {
        for(int ii=0; ii < msgCount; ii++) {
            list.add(c.getString(c.getColumnIndexOrThrow("address")).toString());
            c.moveToNext();
        }
    }
    phoneListView.setAdapter(new ArrayAdapter<String>(BankActivity.this, android.R.layout.simple_dropdown_item_1line, list));

Ajout du mot-clé Distinct dans la projection a fonctionné pour moi aussi, cependant, il ne fonctionnait que lorsque le mot-clé distinct a été le premier argument:

String[] projection = new String[]{"DISTINCT " + DBConstants.COLUMN_UUID, ... };

Peut-être son plus simple d'obtenir des valeurs distinctes, essayez d'ajouter le mot DISTINCT avant le nom de la colonne que vous voulez dans la table de projection

String[] projection = new String[]{
                BaseColumns._ID,
                "DISTINCT "+ Mediastore.anything.you.want
};

et l'utiliser comme un argument pour interroger la méthode du résolveur de contenu!

Je l'espère pour vous aider, parce que j'ai la même question avant quelques jours

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top