2010-02-22 45 views
28

Điều gì sẽ là một cách hợp lý để thêm các yêu cầu DISTINCT và/hoặc GROUPBY đến ContentResolver - dựa trên. Ngay bây giờ tôi phải tạo URI tùy chỉnh cho từng trường hợp đặc biệt. Có cách nào tốt hơn? (Tôi vẫn là chương trình cho 1.5 là mẫu số chung thấp nhất)Android: Khác biệt và GroupBy trong ContentResolver

Trả lời

11

Vì không ai trả lời tôi sẽ chỉ cho tôi cách giải quyết vấn đề này. Về cơ bản, tôi sẽ tạo URI tùy chỉnh cho từng trường hợp và chuyển các tiêu chí trong thông số selection. Sau đó, bên trong ContentProvider#query Tôi sẽ xác định trường hợp và xây dựng truy vấn thô dựa trên tên bảng và thông số lựa chọn.

Dưới đây là ví dụ nhanh:

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); 
+10

công việc này chỉ khi bạn có bàn tay trên nhà cung cấp ... – njzk2

+0

@ njzk2 Nếu tôi hiểu bạn một cách chính xác, bạn đang nói rằng nó có thể để có được ví dụ của các địa chỉ liên lạc thực tế db? –

+0

@Ilya_Gazman no, tôi nói rằng giải pháp này chỉ hoạt động nếu bạn là người triển khai nhà cung cấp nội dung. – njzk2

38

Bạn có thể làm đẹp Hack khi truy vấn contentResolver, sử dụng:

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

Rất hay nếu bạn không có quyền truy cập vào nguồn ContentProvider. Cảm ơn bạn. –

+0

rất dễ dàng và hoạt động tốt nhưng cách sử dụng DISTINCT? – Amal

+0

xin lỗi lỗi của tôi tôi đã sử dụng GROUP BY với cột tôi muốn phân biệt với tôi không tốt trong SQL – Amal

13

Trong ghi đè ContentProvider phương pháp truy vấn của bạn có một ánh xạ URI cụ thể để sử dụng riêng biệt.

Sau đó, sử dụng SQLiteQueryBuilder và gọi phương thức 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; 
} 
+1

mDBHelper là gì? – Hamidreza

-1

Có lẽ nó đơn giản hơn để có được giá trị khác biệt, cố gắng thêm từ DISTINCT trước tên cột mà bạn muốn vào bảng chiếu

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

và sử dụng nó như một cuộc tranh cãi để truy vấn phương pháp trình phân giải nội dung!

tôi hy vọng sẽ giúp bạn, vì tôi có cùng một câu hỏi trước vài ngày

+3

Điều này không hiệu quả đối với tôi. Mã của tôi: \t \t Chuỗi [] chiếu = chuỗi mới [] {"DISTINCT" \t \t \t \t + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME}; \t \t Cursor cur = cr.query ( \t \t \t \t ContactsContract.CommonDataKinds.Phone.CONTENT_URI, chiếu, \t \t \t \t "LENGTH (" + ContactsContract.CommonDataKinds.Phone.NUMBER \t \t \t \t \t \t + ")> = 8", null, sortOrder); Tôi nhận được cột không hợp lệ DISTINCT display_name – Maurice

+0

Cho phép thử thêm dấu cách tại "DISTINCT" -> "DISTINCT"; Tại blog này http://javment.blogspot.com/2011/07/how-to-get-distinct-values-from-android.html Tôi đã thực hiện một hướng dẫn đơn giản về điều này, có thể giúp bạn. – javment

+4

Điều này không hiệu quả đối với tôi. Ngay cả với không gian –

0

Trong một số điều kiện, chúng ta có thể sử dụng "riêng biệt (column_name)" như việc lựa chọn, và nó hoạt động hoàn hảo. nhưng trong một số điều kiện, nó sẽ gây ra một ngoại lệ.

khi nó gây ra một ngoại lệ, tôi sẽ sử dụng một HashSet để lưu trữ các giá trị cột ....

9

Nếu bạn muốn sử dụng DISTINCT với SELECT hơn sau đó một cột, Bạn cần sử dụng GROUP BY.
Mini Hack qua ContentResolver.query để sử dụng này:

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

Mã này chọn một sms cuối cùng cho mỗi người gửi từ hộp thư đến thiết bị.
Lưu ý: trước khi GROUP BY chúng tôi luôn cần viết ít nhất một điều kiện. Kết quả chuỗi truy vấn SQL bên trong phương pháp ContentResolver.query sẽ:

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

Cảm ơn! bạn đã cứu cuộc sống của tôi :) –

5

Mặc dù tôi đã không sử dụng Nhóm By, tôi đã sử dụng biệt trong truy vấn phân giải nội dung.

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

+2

hoạt động đúng nhờ –

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)); 
+0

bạn nên giải thích rõ hơn câu trả lời của mình –

0

Thêm từ khóa riêng biệt trong dự báo làm việc cho tôi quá, tuy nhiên, nó chỉ làm việc khi từ khóa riêng biệt là đối số đầu tiên:

String[] projection = new String[]{"DISTINCT " + DBConstants.COLUMN_UUID, ... }; 
Các vấn đề liên quan