34

ベースのクエリを追加DISTINCTおよび/または追加する正しい方法は何でしょうか?GROUPBYContentResolver

今のところ、特別な場合ごとにカスタムURIを作成する必要があります。

もっと良い方法はありますか?

(私はまだ最小公分母として1.5をプログラムしています)

4

11 に答える 11

43

contentResolverにクエリを実行するときに、次のコマンドを使用して、すばらしいハックを行うことができます。

String selection = Models.SOMETHING + "=" + something + ") GROUP BY (" + Models.TYPE;
于 2010-12-17T11:59:54.790 に答える
19

SELECTで複数の列を指定してDISTINCTを使用する場合は、GROUPBYを使用する必要があります。
これを使用するための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を1つ選択します。
注:GROUP BYの前に、常に少なくとも1つの条件を記述する必要があります。ContentResolver.queryメソッド内の結果のSQLクエリ文字列は次のようになります。

SELECT DISTINCT address, body FROM sms WHERE (type=1) AND (address IS NOT NULL) GROUP BY (address) 
于 2013-04-30T13:37:25.173 に答える
15

誰も答えに来なかったので、私はこれをどのように解決したかを説明します。基本的に、ケースごとにカスタム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);
于 2010-02-27T20:13:02.127 に答える
14

オーバーライドさContentProviderれたクエリメソッドには、distinctを使用するための特定の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;
}
于 2010-12-20T20:02:06.043 に答える
7

Group Byは使用していませんが、コンテンツリゾルバークエリでDistinctを使用しています。

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

于 2015-08-20T05:37:37.963 に答える
1

射影にDistinctキーワードを追加することも私にとってはうまくいきましたが、distinctキーワードが最初の引数である場合にのみ機能しました。

String[] projection = new String[]{"DISTINCT " + DBConstants.COLUMN_UUID, ... };
于 2017-02-11T14:58:29.863 に答える
0

条件によっては、「distinct(COLUMN_NAME)」を選択として使用でき、完全に機能します。ただし、条件によっては例外が発生します。

例外が発生した場合は、HashSetを使用して列の値を格納します。

于 2012-05-07T06:39:36.377 に答える
0
// 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));
于 2016-02-09T15:21:28.387 に答える
0

投影に複数の列がある場合は、次のようにする必要があります。

    val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val projection = arrayOf(
        "DISTINCT " + MediaStore.Images.Media.BUCKET_ID,
        MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
        MediaStore.Images.Media.BUCKET_ID,
        MediaStore.MediaColumns.DATA
    )
    val groupBySelection = " 1) GROUP BY (${MediaStore.Images.Media.BUCKET_ID}"
    contentResolver.query(
        uri,
        projection,
        null,
        groupBySelection,
        null,
        null
    )

閉じ括弧と数字「1」が内部にあるgroupBySelectionは小さなハックですが、完全に正常に機能します

于 2020-04-15T16:08:08.443 に答える
0

groupbyとdistinctを使用するためのユーティリティメソッドを作成しました。

使用法

thread_idこれは、MMSデータベースから最後のメッセージ日付で未表示を選択する例です。

query(contentResolver= contentResolver,
        select = arrayOf(Mms.THREAD_ID, "max(${Mms.DATE}) as date"),
        from = Mms.CONTENT_URI,
        where = "${Mms.SEEN} = 0",
        groupBy = "1",
        orderBy = "2 desc"
        ).use {
    while (it?.moveToNext() == true){
        val threadId = it.getInt(0)
        val date = it.getLong(1)
    }
}

ソース

fun query(
        contentResolver: ContentResolver,
        from: Uri,
        select: Array<String>,
        where: String? = null,
        groupBy: Array<out String>? = null,
        distinct: Boolean = false,
        selectionArgs: Array<out String>? = null,
        orderBy: String? = null,
): Cursor? {
    val tmpSelect = select[0]
    val localWhere =
            if (groupBy == null) where
            else "${where ?: "1"}) group by (${groupBy.joinToString()}"
    if (distinct) {
        select[0] = "distinct $tmpSelect"
    }
    val query = contentResolver.query(from, select, localWhere, selectionArgs, orderBy)
    select[0] = tmpSelect
    return query
}
于 2021-04-01T16:58:21.460 に答える
-1

明確な値を取得する方が簡単かもしれませんが、プロジェクションテーブルの列名の前にDISTINCT単語を追加してみてください

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

そしてそれをコンテンツリゾルバーのクエリメソッドへの引数として使用してください!

私はあなたを助けたいと思っています、なぜなら私は数日前に同じ質問をするからです

于 2011-06-28T12:51:11.480 に答える