سؤال

ماذا سيكون طريقة معقولة للإضافة DISTINCT و/أو GROUPBY إلى ContentResolver- الاستفسارات القائمة. الآن لا بد لي من إنشاء URI مخصص لكل حالة خاصة. هل هناك طريقة أفضل؟ (ما زلت برنامجًا لـ 1.5 كأدنى قاسم مشترك)

هل كانت مفيدة؟

المحلول 2

بما أنه لم يأت أحد للإجابة ، فسأخبرني كيف حللت هذا. في الأساس ، سأقوم بإنشاء 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);

نصائح أخرى

يمكنك القيام بالاختراق الجميل عند الاستعلام عن contentResolver ، استخدم:

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

إذا كنت ترغب في استخدام متميز مع SELECT أكثر من عمود واحد ، فأنت بحاجة إلى استخدام Group بواسطة.
Mini Hack عبر 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());
        }

حدد هذا الرمز الرسائل القصيرة الأخيرة لكل من المرسلين من صندوق الوارد.
ملاحظة: قبل المجموعة ، نحتاج دائمًا إلى كتابة حالة واحدة على الأقل. النتيجة SQL Query String داخل contentResolver.query طريقة:

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

في تجاوزك 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;
}

على الرغم من أنني لم أستخدم مجموعة من, ، لقد استخدمت مميز في استعلام حل المحتوى.

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

في بعض الحالات ، يمكننا استخدام "Distore (column_name)" كتحديد ، ويعمل بشكل مثالي. ولكن في حالة ما ، سوف يسبب استثناء.

عندما تسبب استثناء ، سأستخدم مجموعة التجزئة لتخزين قيم العمود ....

// 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));

إضافة الكلمة الرئيسية المتميزة في الإسقاط عملت بالنسبة لي أيضًا ، ومع ذلك ، فقد نجحت فقط عندما كانت الكلمة الرئيسية المتميزة هي الوسيطة الأولى:

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

ربما يكون من السهل الحصول على قيم متميزة ، حاول إضافة الكلمة المتميزة قبل اسم العمود الذي تريده في جدول الإسقاط

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

واستخدامه كوسيطة للاستعلام عن محدد المحتوى!

آمل أن أساعدك ، لأن لدي نفس السؤال قبل بعض الأيام

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top