Android: Distinct et GroupBy dans ContentResolver
quelle serait une façon sensée d'ajouter DISTINCT
et/ou GROUPBY
ContentResolver
base de requêtes. En ce moment je dois créer URI personnalisé pour chaque cas spécial. Est-il un meilleur moyen?
(J'ai encore de programme pour 1.5 comme plus petit dénominateur commun)
9 réponses
Vous pouvez faire de belles hack lors de l'interrogation contentResolver, utilisez:
String selection = Models.SOMETHING + "=" + something + ") GROUP BY (" + Models.TYPE;
puisque personne n'est venu pour répondre, je vais juste dire comment j'ai résolu cela. Fondamentalement, je créerais URI personnalisé pour chaque cas et passer les critères dans selection
paramètre. Puis à l'intérieur de ContentProvider#query
j'identifierais le cas et construirais la requête brute basée sur le nom de la table et le paramètre de sélection.
Voici un exemple rapide:
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);
Dans votre substituée ContentProvider
la méthode de requête a un URI spécifique qui correspond à l'utilisation de distinct.
alors utilisez SQLiteQueryBuilder
et appelez le setDistinct(boolean)
méthode.
@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;
}
si vous voulez utiliser DISTINCT avec SELECT more then one column, vous devez utiliser GROUP BY.
Mini Hack sur ContentResolver.requête pour utiliser ceci:
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());
}
ce code sélectionnez un dernier sms pour chacun des expéditeurs à partir de la boîte de réception de l'appareil.
Note: Avant groupe par nous avons toujours besoin d'écrire au moins une condition.
Résultat chaîne de requête SQL dans ContentResolver.méthode de requête:
SELECT DISTINCT address, body FROM sms WHERE (type=1) AND (address IS NOT NULL) GROUP BY (address)
Bien que je n'ai pas utilisé Group By, j'ai utilisé Distinct dans la requête content resolver.
Cursor cursor = contentResolver
.query(YOUR_URI,
new String[] {"Distinct "+ YOUR_COLUMN_NAME},
null,
null, null);
dans certaines conditions, nous pouvons utiliser "distinct (COLUMN_NAME)" comme sélection, et il travail parfait. mais dans certaines conditions, il causera une exception.
quand il cause une exception, j'utiliserai un HashSet pour stocker les valeurs de la colonne....
// 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));
ajouter le mot-clé Distinct dans la projection a fonctionné pour moi aussi, cependant, il n'a fonctionné que lorsque le mot-clé distinct était le premier argument:
String[] projection = new String[]{"DISTINCT " + DBConstants.COLUMN_UUID, ... };
peut-être est-il plus simple d'obtenir des valeurs distinctes, essayez d'ajouter le mot DISTINCT avant le nom de la colonne que vous voulez dans la table de projection
String[] projection = new String[]{
BaseColumns._ID,
"DISTINCT "+ Mediastore.anything.you.want
};
et l'utiliser comme un argument à la méthode de requête de contenu résolveur!
j'espère pouvoir vous aider, car j'ai la même question que dans quelques jours