SQLite获取具有最大值的行

时间:2018-02-24 21:10:41

标签: android sqlite

所以我有一个填充数据库的列:_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.我知道有很多类似的问题,但我看着男人仍然无法找到解决方案......

1 个答案:

答案 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)