Android / SQLite - 跨多个列的不同计数

时间:2014-07-03 20:46:21

标签: android sqlite count distinct

我有以下代码......

protected long getNumQueuedChunks(boolean distinctEntries) throws Exception {

SQLiteDatabase db = null;
try {

    db = dbhelper.getReadableDatabase();

    String whereClause = C_STATUS + " = ? AND " + C_NUM_FAILURES + " < ?";
    String[] whereArgs = new String[] {STATUS_AWAITING_PROCESSING, 10};

    long count = DatabaseUtils.queryNumEntries(db, QUEUE_TABLE_NAME, whereClause, whereArgs);           
    return count;
}
finally {
    try {
        db.close();
    }
    catch(Exception ignore) {
    }
}

}

...如果我想返回与WHERE条件匹配的行总数,它可以正常工作。

但是,我想只计算在这3列中具有不同/唯一数据组合的记录:C_URI,C_BYTE_START_NUM和C_NUM_BYTES。

我知道我可以做点像......

    String[] columns = {C_URI, C_BYTE_START_NUM, C_NUM_BYTES};
String whereClause = C_STATUS + " = ? AND " + C_NUM_FAILURES + " < ?";
String[] whereArgs = new String[] {STATUS_AWAITING_PROCESSING, "10"};
Cursor c = db.query(true, QUEUE_TABLE_NAME, columns, whereClause, whereArgs, null, null, null, null);
int count = c.getCount();

...但我希望在这种情况下有一种更有效的方法来执行一个独特的计数?

只是为了增加清晰度,如果我在表格中有这些数据......

C_URI | C_BYTE_START_NUM | C_NUM_BYTES

1.jpg | 0 | 1024

1.jpg | 1024 | 1999年

2.jpg | 0 | 500

2.jpg | 0 | 500

...非重复计数的结果应为3。

注意 - 我已经看到了here (second answer)所描述的类似要求,但这对我没有帮助,因为我想要对3列进行不同的计数,而不只是一个。

2 个答案:

答案 0 :(得分:4)

计算记录的最有效方法是让数据库执行此操作:

SELECT COUNT(*)
FROM (SELECT DISTINCT Uri,
                      ByteStartNum,
                      NumBytes
      FROM QueueTable)

(使用单独的子查询,如果在三列上使用DISTINCT或GROUP BY,则无关紧要。)

此查询不适合其中一个辅助函数(如queryqueryNumEntries)的约束,因此您必须手动构造整个SQL语句:

long getNumQueuedChunks() {
    SQLiteDatabase db = dbhelper.getReadableDatabase();
    try {
        String query = "SELECT COUNT(*) FROM " +
                        "(SELECT DISTINCT " + C_URI + "," + C_BYTE_START_NUM + "," + C_NUM_BYTES +
                        " FROM " + QUEUE_TABLE_NAME +
                        " WHERE " + C_STATUS + " = ?" +
                        " AND " + C_NUM_FAILURES + " < 10)";
        String[] args = new String[] { STATUS_AWAITING_PROCESSING };
        return DatabaseUtils.longForQuery(db, query, args);
    } finally {
        db.close();
    }
}

答案 1 :(得分:1)

您是否尝试过SQLiteDatabase.rawQuery()方法?您可以在其中放置原始SQL查询,例如:

select distinct C_URI, C_BYTE_START_NUM, C_NUM_BYTES from MyTable 

该方法返回一个Cursor,您可以立即从游标对象获取计数。当然,如果您愿意,也可以指定where子句。然后在计算完毕后释放光标。