所以我有一个填充数据库的列:_ID,excersise,reps和timestamp。我试图用这个Cursor打印出具有最高代表号的行:
private Cursor getRepRecord(String excersise) {
return myDatabase.query(Contact.ExcersiseEntry.TABLE_NAME,
new String [] {"MAX(reps)"},
Contact.ExcersiseEntry.EXCERSISE_NAME + "= '" + excersise + "'",
null,
null,
null,
Contact.ExcersiseEntry.EXCERSISE_REPS + " DESC");
}
然后我用这个方法来打印游标行:
private void getEntryFromDatabase(Cursor cursor) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String excersise = cursor.getString(cursor.getColumnIndex(Contact.ExcersiseEntry.EXCERSISE_NAME));
int reps = cursor.getInt(cursor.getColumnIndex(Contact.ExcersiseEntry.EXCERSISE_REPS));
int id = cursor.getInt(cursor.getColumnIndex(Contact.ExcersiseEntry._ID));
Log.i("Entry", "ID: " +id + " || Excersise: " + excersise + " || reps: " + Integer.toString(reps));
cursor.moveToNext();
}
}
我怎么得到错误:CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 1 columns.
我知道有很多类似的问题,但我看着男人仍然无法找到解决方案......
答案 0 :(得分:0)
您获得-1的原因是因为您尝试从中提取数据的列在Cursor中不存在(如果找不到该列,则getColumnIndex
方法返回-1)。
Cursor只有一个名为MAX(reps)
的列。
您可以通过用逗号添加*(与MAX(reps
)列分隔来轻松添加所有其他列,也可以单独添加其他列作为数组的元素。如果要显示最大代表,您将提取名为MAX(reps)
的列,或者您可以使用AS重命名该列,例如MAX(reps) as maxreps
所以你可以: -
private Cursor getRepRecord(String excersise) {
return myDatabase.query(Contact.ExcersiseEntry.TABLE_NAME,
new String [] {"MAX(reps) AS maxreps", *}, //<<<< Changed
Contact.ExcersiseEntry.EXCERSISE_NAME + " = '" + excersise + "'",
null,
null,
null,
Contact.ExcersiseEntry.EXCERSISE_REPS + " DESC");
}
这可以与稍加修改的getEntryFromDatabase
方法一起使用: -
private void getEntryFromDatabase(Cursor cursor) {
//cursor.moveToFirst(); //<<< does nothing of any use as return value is ignored
while (!cursor.isAfterLast()) {
String excersise = cursor.getString(cursor.getColumnIndex(Contact.ExcersiseEntry.EXCERSISE_NAME));
int reps = cursor.getInt(cursor.getColumnIndex(Contact.ExcersiseEntry.EXCERSISE_REPS)); // Would this be of any use???
int id = cursor.getInt(cursor.getColumnIndex(Contact.ExcersiseEntry._ID));
int maxreps = cursor.getInt(cursor.getColumnIndex("maxreps")); //<<<< Added
Log.i("Entry", "ID: " +id + " || Excersise: " + excersise + " || reps: " + Integer.toString(reps) + " || maxreps: " + Integer.toString(maxreps);
cursor.moveToNext();
}
}
我还是不太明白为什么。正确的SQL术语是 类似于SELECT * WHERE reps = max(reps),对吗?怎么做的 转换成Max(reps),*
如果您使用SELECT * FROM reps WHERE reps = Max(reps)
,它将返回所有已定义的列(*
转换为所有列),这些行等于最高重复值(注意见下文为什么这会起作用)。这可能是你想要的。 (ORDER BY reps DESC(或ASC)无关紧要)。
SELECT(SELECT ALL或SELECT DISTINCT)之后的列列表定义了result_columns,即结果Cursor中将存在的列。如果你说SELECT reps FROM reps
那么结果游标将只有1列名为reps。 SELECT reps, exercise
然后生成的游标将有两列。
SQL允许派生列(我的术语)。派生列名称将采用用于派生值的表达式的名称。因此,如果您说SELECT max(reps) FROM reps
,那么结果将是一个名为 max(reps)的列的Cursor(并且因为MAX是一个聚合函数1行(除非使用GROUP BY))。
您的代码中使用的查询方法(总共有4个)具有签名: -
Cursor query (String table,
String[] columns, //<<<< list of result columns
String selection, //<<<< WHERE CLAUSE
String[] selectionArgs,
String groupBy,
String having,
String orderBy)
所以: -
myDatabase.query(Contact.ExcersiseEntry.TABLE_NAME,
new String [] {"MAX(reps)"},
Contact.ExcersiseEntry.EXCERSISE_NAME + "= '" + excersise + "'",
null,
null,
null,
Contact.ExcersiseEntry.EXCERSISE_REPS + " DESC");
导致SQL SELECT MAX(reps) FROM reps WHERE excercise = 'your_excercise'
;
因此,生成的Cursor将有一列名为MAX(reps)
。
如果你想要SELECT * FROM reps WHERE reps = MAX(reps)
,那么你可以使用: -
myDatabase.query(Contact.ExcersiseEntry.TABLE_NAME,
null, //<<<< ALL columns
Contact.ExcersiseEntry.EXCERSISE_REPS + " = MAX(reps)",
null,
null,
null,
Contact.ExcersiseEntry.EXCERSISE_REPS + " DESC" // Irrelevant
);
然而,这将适用于所有练习,因此可以返回多行但是它会滥用聚合函数(尝试在每行的基础上应用函数而不是在每个组的基础上应用函数(所有行是组,因为没有指定GROUP BY))。
SELECT * FROM reps WHERE reps = (SELECT MAX(reps) FROM reps)