2010-02-22 3 views
28

Was wäre eine sinnvolle Möglichkeit DISTINCT und/oder GROUPBY zu ContentResolver - basierten Abfragen hinzuzufügen. Im Moment muss ich für jeden Spezialfall einen eigenen URI erstellen. Gibt es einen besseren Weg? (Ich programmiere immer noch für 1.5 als kleinsten gemeinsamen Nenner)Android: Distinct und GroupBy in ContentResolver

Antwort

11

Da niemand kam um zu antworten, werde ich nur erzählen, wie ich das gelöst habe. Grundsätzlich würde ich benutzerdefinierte URI für jeden Fall erstellen und die Kriterien in selection Parameter übergeben. Dann innerhalb ContentProvider#query Ich würde den Fall identifizieren und rohe Abfrage basierend auf Tabellenname und Auswahlparameter erstellen.

Hier ist schnelles Beispiel:

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

diese Arbeit nur, wenn Sie die Hand auf den Provider ... – njzk2

+0

@ njzk2 Wenn ich Sie richtig verstehe, Sie sagen, dass es möglich ist, die Instanz der tatsächlichen Kontakte db zu bekommen? –

+0

@Ilya_Gazman nein, ich sage, dass diese Lösung nur funktioniert, wenn Sie derjenige sind, der den Inhaltsanbieter implementiert. – njzk2

38

Sie können schön Hack tun, wenn contentResolver Abfrage Verwendung:

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

Nice Hack, wenn Sie keinen Zugriff auf ContentProvider-Quelle haben. Vielen Dank. –

+0

es ist sehr einfach und funktioniert gut, aber wie DISTINCT zu verwenden? – Amal

+0

Entschuldigung es ist meine Schuld Ich verwendete GROUP BY mit der Spalte, die ich mit INTELLIGENZ mit mir nicht gut sein wollte – Amal

13

In Ihrem überschrieben ContentProvider Abfragemethode eine spezifische URI Mapping unterschiedliche Verwendung.

Dann verwenden Sie SQLiteQueryBuilder und rufen Sie die setDistinct(boolean) Methode.

@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

Was ist der mDBHelper? – Hamidreza

-1

Vielleicht ist es einfacher verschiedene Werte zu bekommen, versuchen, das DISTINCT Wort vor dem Spaltennamen in den Projektionstisch

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

und als Argument verwenden willst, dass es in der Abfrage-Methode von der Content-Resolver!

Ich hoffe, Ihnen zu helfen, weil ich die gleiche Frage vor einigen Tagen

+3

Das funktioniert nicht für mich. Mein Code: \t \t String [] Projektion = new String [] { "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, Projektion, \t \t \t \t "Länge (" + ContactsContract.CommonDataKinds.Phone.NUMBER \t \t \t \t \t \t + ")> = 8", null, sortOrder); Ich bekomme ungültige Spalte DISTINCT display_name – Maurice

+0

Lets versuchen, ein Leerzeichen bei "DISTINCT" hinzufügen -> "DISTINCT"; In diesem Blog http://javment.blogspot.com/2011/07/how-to-get-distinct-values-from-android.html Ich habe ein einfaches Tutorial dazu gemacht, kann Ihnen helfen. – javment

+4

Das hat nicht für mich funktioniert. Selbst mit dem Leerzeichen –

0

In einigen Zustand haben, können wir „distinct (COLUMN_NAME)“ als Auswahl verwenden, und perfekt funktionieren. aber in einigen Bedingungen wird eine Ausnahme verursacht.

, wenn es eine Ausnahme verursachen, werde ich eine HashSet verwenden, um die Spaltenwerte zu speichern ....

9

Wenn Sie mit SELECT mehr DISTINCT verwenden möchten dann eine Spalte, müssen Sie GROUP BY verwenden.
Mini Hack über ContentResolver.query für die Verwendung dieser:

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

Dieser Code eine letzte SMS für jede der Absender von Gerät Posteingang wählen.
Hinweis: Vor GROUP BY müssen wir immer mindestens eine Bedingung schreiben. Ergebnis SQL-Abfrage-String innerhalb ContentResolver.query Methode wird:

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

Danke! Du hast mein Leben gerettet :) –

5

Obwohl ich nicht Gruppe von verwendet habe, habe ich Distinct in Content-Resolver-Abfrage verwendet.

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

+2

funktioniert richtig dank –

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

du solltest deine Antwort besser erklären –

0

das Schlüsselwort distinct in der Projektion für mich gearbeitet zu Hinzufügen, es jedoch funktionierte nur, wenn das Schlüsselwort distinct das erste Argument war:

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