Android - 在contentProvider中选择max

问题描述:

我尝试在自定义contentprovider上运行此查询。Android - 在contentProvider中选择max

cursor = activity.getContentResolver().query(
       GoalDescriptor.CONTENT_URI, 
       "max(priority)", null, 
       null, null); 

获取优先级int列的最大值。

我也尝试:

cursor = activity.getContentResolver().query(
       GoalDescriptor.CONTENT_URI, 
       null, "max(priority)", 
       null, null); 

丝毫没有成功。

该代码返回此异常:

java.lang.IllegalArgumentException: Invalid column MAX(priority) 
E/DatabaseUtils( 688):  at android.database.sqlite.SQLiteQueryBuilder.computeProjection(SQLiteQueryBuilder.java:523) 
E/DatabaseUtils( 688):  at android.database.sqlite.SQLiteQueryBuilder.buildQuery(SQLiteQueryBuilder.java:370) 
E/DatabaseUtils( 688):  at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:323) 
E/DatabaseUtils( 688):  at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:280) 
E/DatabaseUtils( 688):  at nan.salsa.contentprovider.goal.GoalContentProvider.query(GoalContentProvider.java:118) 
E/DatabaseUtils( 688):  at android.content.ContentProvider$Transport.bulkQuery(ContentProvider.java:150) 
E/DatabaseUtils( 688):  at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:111) 
E/DatabaseUtils( 688):  at android.os.Binder.execTransact(Binder.java:288) 
E/DatabaseUtils( 688):  at dalvik.system.NativeStart.run(Native Method) 
D/AndroidRuntime( 727): Shutting down VM 

我的内容提供者实现(标准 - 见记事本样品)

public Cursor query(Uri uri, String[] projection, String selection, 
     String[] selectionArgs, String sortOrder) { 
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 
    qb.setTables(GoalDescriptor.TABLE_NAME); 

    switch (sUriMatcher.match(uri)) { 

    case GOAL: 
     qb.setProjectionMap(sGoalProjectionMap); 
     qb.appendWhere(GoalDescriptor._ID + "=" 
       + uri.getPathSegments().get(1)); 
     break; 

    case GOALS: 
     qb.setProjectionMap(sGoalProjectionMap); 
     break; 

    default: 
     throw new IllegalArgumentException("Unknown URI " + uri); 
    } 

    // If no sort order is specified use the default 
    String orderBy; 
    if (TextUtils.isEmpty(sortOrder)) { 
     orderBy = GoalInfo.GoalDescriptor.DEFAULT_SORT_ORDER; 
    } else { 
     orderBy = sortOrder; 
    } 

    // Get the database and run the query 
    SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 
    Cursor c = qb.query(db, projection, selection, selectionArgs, null, 
      null, orderBy); 

    // Tell the cursor what uri to watch, so it knows when its source data 
    // changes 
    c.setNotificationUri(getContext().getContentResolver(), uri); 
    return c; 
} 

你能帮助我吗?

问候

+0

在MyTouch操作系统2.1(不知道SQLite的版本)上,我的语法对我有效,但在我的G2上失败:( – mobibob 2011-04-22 06:09:16

您发送的最大(优先级)的投影,在把它作为选择,它应该工作。

看到这个问题: Android: Get highest value in column

编辑:

看来这应该工作:

cursor = activity.getContentResolver().query(
     GoalDescriptor.CONTENT_URI, 
      new String[] {"MAX(priority) AS max_priority"}, null, 
     null, null); 
+1

我看到了,但这个解决方案对我来说不起作用... – 2011-02-15 17:04:43

遗憾的是NEX的回答(使用 “AS”,以提供列的别名)只与不在其SQLiteQueryBuilder中设置strictProjectionMap标志的提供者一起工作。例如。联系人提供程序设置此标志,因此如果您尝试使用AS方法,则仍然会出现“无效列”错误。

如果有人能告诉我如何在选择中指定像MAX这样的聚合函数应该工作,我会非常感激。如果我尝试它,我只会得到一个“滥用聚合函数”异常,这正是我期望尝试将聚合函数放在WHERE子句中的结果。我知道你可以在WHERE子句中放置一个子查询,但是假设你知道实际的表结构,并且它在任何给定的设备或操作系统级别都不会改变,我不想打赌(毕竟,这就是为什么首先使用提供者接口,从底层数据存储抽象出来的原因)。

因此......我不知道有什么办法可以为设置strictProjectionMap标志的提供者执行此操作,而不是根据所需字段对DESC进行排序,并且如果提供程序支持,最好将LIMIT设置为1行(或者if你愿意通过在排序字符串中包含LIMIT来打破某些事情)。如果有人知道这些案例的其他方法,我会非常高兴!

在我的情况下,nEx的答案确实有效,但我忘了在光标的getColumnIndexByName()方法中添加“max _”+ COLUMN_NAME。

我想通了之后,这也得到了改变,终于奏效了!