2010-02-22 8 views
28

Jaki byłby rozsądny sposób dodawania zapytań opartych na DISTINCT i/lub do na . Teraz muszę utworzyć niestandardowy identyfikator URI dla każdego przypadku specjalnego. Czy istnieje lepszy sposób? (Nadal programuję dla 1,5 jako najniższy wspólny mianownik)Android: Odrębny i GroupBy w ContentResolver

Odpowiedz

11

Ponieważ nikt nie przyszedł odpowiedzieć, po prostu powiem, jak to rozwiązałem. Zasadniczo chciałbym utworzyć niestandardowy identyfikator URI dla każdego przypadku i spełnić kryteria w parametrze selection. Następnie wewnątrz ContentProvider#query chciałbym zidentyfikować sprawę i skonstruować surowe zapytanie oparte na nazwie tabeli i parametrze wyboru.

Oto krótki przykład:

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

tej pracy tylko wtedy, gdy masz ręka dostawcy ... – njzk2

+0

@ njzk2 Jeśli dobrze cię rozumiem, mówisz, że można uzyskać instancję db danych kontaktów? –

+0

@Ilya_Gazman nie, mówię, że to rozwiązanie działa tylko wtedy, gdy jesteś tym, który wdraża dostawcę zawartości. – njzk2

38

można zrobić piękny siekać podczas odpytywania contentResolver, przeznaczenie:

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

Fajny hack, jeśli nie masz dostępu do źródła ContentProvider. Dziękuję Ci. –

+0

jest bardzo prosta i działa dobrze, ale jak korzystać z DISTINCT? – Amal

+0

Przepraszam, że moja wina użyłem GROUP BY z kolumną, którą chciałem WYCIĄGNĄĆ z nie jestem dobry w SQL – Amal

13

W swojej zamienione na ContentProvider metody zapytań mają szczególne odwzorowanie URI do korzystania odrębne.

Następnie użyj SQLiteQueryBuilder i zadzwoń na metodę 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

co to jest mDBHelper? – Hamidreza

-1

Być może jest to bardziej proste, aby uzyskać różne wartości, spróbować dodać DISTINCT słowo przed nazwą kolumny chcesz do stołu projekcyjnego

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

i używać go jako argumentu do kwerendy metody resolver zawartości!

mam nadzieję pomóc, bo mam to samo pytanie kilka dni przed

+3

To nie działa dla mnie. My Kod: \t \t ciąg [] = projekcja nowy ciąg [] { "różny" \t \t \t \t + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME}; \t \t kursora bież = cr.query ( \t \t \t \t ContactsContract.CommonDataKinds.Phone.CONTENT_URI, odwzorowanie \t \t \t \t "długość (" + ContactsContract.CommonDataKinds.Phone.NUMBER \t \t \t \t \t \t + ")> = 8", null, sortOrder); Otrzymuję niepoprawną kolumnę DISTINCT display_name – Maurice

+0

Pozwala spróbować dodać spację w "DISTINCT" -> "DISTINCT"; Na tym blogu http://javment.blogspot.com/2011/07/how-to-get-distinct-values-from-android.html Zrobiłem prosty tutorial na ten temat, może ci pomóc. – javment

+4

To nie działa dla mnie. Nawet przy przestrzeni –

0

w niektórych warunkach, możemy użyć „odrębny (COLUMN_NAME)” jako wybór, i to działało idealnie. ale w niektórych warunkach spowoduje to wyjątek.

kiedy to spowodować wyjątek, użyję HashSet do przechowywania wartości kolumny ....

9

Jeśli chcesz korzystać z DISTINCT wybrać więcej niż jedną kolumnę, trzeba użyć GROUP BY.
Mini Hack nad ContentResolver.query do stosowania tego:

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

Ten kod Wybierz jedną ostatnią SMS dla każdego z nadawców ze skrzynki odbiorczej urządzenia.
Uwaga: przed GROUP BY zawsze musimy zapisać co najmniej jeden warunek. wyniku zapytania SQL ciąg wewnątrz metody ContentResolver.query będzie:

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

Dzięki! uratowałeś mi życie :) –

5

Choć nie użyłem Grupa Poprzez, Użyłem odrębne w treści zapytania przelicznika.

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

+2

działa poprawnie dzięki –

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

lepiej wytłumaczyć swoją odpowiedź –

0

Dodawanie DISTINCT w projekcji pracował dla mnie zbyt jednak, że działa tylko wtedy, gdy DISTINCT był pierwszy argument:

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