Android: отличительные и групповые в ContentResolver - PullRequest
30 голосов
/ 23 февраля 2010

Какой разумный способ добавить DISTINCT и / или GROUPBY к ContentResolver запросам. Прямо сейчас я должен создать собственный URI для каждого особого случая. Есть ли способ лучше? (Я все еще программирую на 1,5 как наименьший общий знаменатель)

Ответы [ 9 ]

40 голосов
/ 17 декабря 2010

Вы можете сделать хороший хак при запросе contentResolver, используйте:

String selection = Models.SOMETHING + "=" + something + ") GROUP BY (" + Models.TYPE;
14 голосов
/ 27 февраля 2010

Поскольку никто не пришел, чтобы ответить, я просто расскажу, как я решил это. По сути, я бы создал собственный URI для каждого случая и передал бы критерии в параметре selection. Затем внутри ContentProvider#query я бы идентифицировал случай и построил необработанный запрос на основе имени таблицы и параметра выбора.

Вот краткий пример:

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);
13 голосов
/ 30 апреля 2013

Если вы хотите использовать DISTINCT с SELECT более чем одним столбцом, вам нужно использовать GROUP BY.
Mini Hack over ContentResolver.query для использования этого:

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());
        }

Этот код выбирает одну последнюю SMS для каждого из отправителей из папки входящих сообщений устройства.
Примечание: перед GROUP BY нам всегда нужно написать хотя бы одно условие. Результирующая строка запроса SQL внутри метода ContentResolver.query будет:

SELECT DISTINCT address, body FROM sms WHERE (type=1) AND (address IS NOT NULL) GROUP BY (address) 
13 голосов
/ 20 декабря 2010

В переопределенном методе запроса ContentProvider есть определенный URI, сопоставляемый с использованием различных.

Затем используйте SQLiteQueryBuilder и вызовите метод 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;
}
6 голосов
/ 20 августа 2015

Хотя я не использовал Group By , я использовал Distinct в запросе распознавателя контента.

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

0 голосов
/ 11 февраля 2017

Добавление ключевого слова Distinct в проекцию также работает для меня, однако оно работает только тогда, когда первым ключевым аргументом было отдельное ключевое слово:

String[] projection = new String[]{"DISTINCT " + DBConstants.COLUMN_UUID, ... };
0 голосов
/ 09 февраля 2016
// 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 голосов
/ 07 мая 2012

В некоторых условиях мы можем использовать «отлично (COLUMN_NAME)» в качестве выбора, и это работает идеально. но в некоторых условиях это вызовет исключение.

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

0 голосов
/ 28 июня 2011

Может быть, проще получить разные значения, попробуйте добавить слово DISTINCT перед желаемым именем столбца в таблицу проекций

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

и используйте его в качестве аргумента для запроса метода распознавателя содержимого!

Я надеюсь помочь вам, потому что у меня есть тот же вопрос до нескольких дней

...