Android: Distinct et GroupBy dans ContentResolver

quelle serait une façon sensée d'ajouter DISTINCT et/ou GROUPBYContentResolver base de requêtes. En ce moment je dois créer URI personnalisé pour chaque cas spécial. Est-il un meilleur moyen? (J'ai encore de programme pour 1.5 comme plus petit dénominateur commun)

30
demandé sur Bostone 2010-02-23 02:54:15

9 réponses

Vous pouvez faire de belles hack lors de l'interrogation contentResolver, utilisez:

String selection = Models.SOMETHING + "=" + something + ") GROUP BY (" + Models.TYPE;
39
répondu kzotin 2010-12-17 11:59:54

puisque personne n'est venu pour répondre, je vais juste dire comment j'ai résolu cela. Fondamentalement, je créerais URI personnalisé pour chaque cas et passer les critères dans selection paramètre. Puis à l'intérieur de ContentProvider#query j'identifierais le cas et construirais la requête brute basée sur le nom de la table et le paramètre de sélection.

Voici un 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);
14
répondu Bostone 2010-02-27 20:13:02

Dans votre substituée ContentProvider la méthode de requête a un URI spécifique qui correspond à l'utilisation de distinct.

alors utilisez SQLiteQueryBuilder et appelez le setDistinct(boolean) méthode.

@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;
}
13
répondu Brady Kroupa 2012-03-22 23:52:56

si vous voulez utiliser DISTINCT avec SELECT more then one column, vous devez utiliser GROUP BY.

Mini Hack sur ContentResolver.requête pour utiliser 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 à partir de la boîte de réception de l'appareil.

Note: Avant groupe par nous avons toujours besoin d'écrire au moins une condition. Résultat chaîne de requête SQL dans ContentResolver.méthode de requête:

SELECT DISTINCT address, body FROM sms WHERE (type=1) AND (address IS NOT NULL) GROUP BY (address) 
12
répondu P-A 2013-04-30 13:37:25

Bien que je n'ai pas utilisé Group By, j'ai utilisé Distinct dans la requête content resolver.

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

5
répondu W00di 2015-08-20 05:37:37

dans certaines conditions, nous pouvons utiliser "distinct (COLUMN_NAME)" comme sélection, et il travail parfait. mais dans certaines conditions, il causera une exception.

quand il cause une exception, j'utiliserai un HashSet pour stocker les valeurs de la colonne....

0
répondu Mikonos 2012-05-07 06:39:36
// 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));
0
répondu Khizhny Andrey 2016-02-09 15:21:28

ajouter le mot-clé Distinct dans la projection a fonctionné pour moi aussi, cependant, il n'a fonctionné que lorsque le mot-clé distinct était le premier argument:

String[] projection = new String[]{"DISTINCT " + DBConstants.COLUMN_UUID, ... };
0
répondu TacoEater 2017-02-11 14:58:29

peut-être est-il 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 à la méthode de requête de contenu résolveur!

j'espère pouvoir vous aider, car j'ai la même question que dans quelques jours

-1
répondu javment 2011-06-28 12:51:11