• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

SQLite order, group, most recent

23tony

Well-Known Member
I'm trying to see if there is a better way to do this than I'm doing. What I have works, but I have to make several DB queries in a loop to get what I want. I'm wondering if there is a better approach that can do it all in a single query. I've tried some things I found on SO and such, but while they worked for MySQL, they use a syntax SQLite doesn't appear to support.

I have a table "messages" with the following data:
Code:
+----+----------+------------+-----------------+---------------------+---------------------+------+
| id | incoming | contact_id | contact_name    | message             | sent                | seen |
+----+----------+------------+-----------------+---------------------+---------------------+------+
|  1 |        0 |         30 | Cap             | Hi there, Cap       | 2019-01-10 15:07:43 |    0 |
|  2 |        1 |         30 | Cap             | Hey, what's up?     | 2019-01-10 15:27:23 |    0 |
|  3 |        0 |         43 | SorcerorSupreme | Strange night, huh? | 2019-01-10 16:42:18 |    0 |
|  4 |        1 |         37 | IAMGROOT        | I am Groot!         | 2019-01-13 09:24:55 |    0 |
|  5 |        0 |         30 | Cap             | Nothing             | 2019-01-14 02:53:28 |    0 |
+----+----------+------------+-----------------+---------------------+---------------------+------+
id, incoming, contact_id, and seen are int, the rest are text

The goal is to get only the last sent message from each contact. For that, I am using the following two functions:
Code:
public ArrayList<Map<String,Object>> loadConversationList() {
    ArrayList<Map<String,Object>> list = new ArrayList();
    SQLiteDatabase db = getReadableDatabase();
    Log.d(TAG, "Getting list of last messages");
    String sql = "SELECT contact_id, max(sent) AS td FROM " + MESSAGE_TABLE + " GROUP BY contact_id ORDER BY td ASC";
    Cursor res = db.rawQuery(sql, null);
    Log.d(TAG, "Made call");
    res.moveToFirst();
    Log.d(TAG, "Set cursor");
    while (!res.isAfterLast()) {
        int contact_id = res.getInt(res.getColumnIndex("contact_id"));
        String sent = res.getString(res.getColumnIndex("td"));
        Log.d(TAG, "Getting info for "+contact_id+":"+sent);
        Map<String, Object> message = getMessage(contact_id, sent);
        list.add(message);
        res.moveToNext();
    }
    Log.d(TAG, list.toString());
    return list;
}

private Map<String,Object> getMessage(int contact_id, String sent) {
    Map<String,Object> message = new HashMap();
    SQLiteDatabase db = getReadableDatabase();
    String sql = "SELECT * FROM " + MESSAGE_TABLE + " WHERE contact_id=" + contact_id + " AND sent='" + sent + "'";
    Cursor res = db.rawQuery(sql, null);
    res.moveToFirst();
    while (!res.isAfterLast()) {
        message.put("mid", res.getString(res.getColumnIndex("id")));
        message.put("incoming", res.getString(res.getColumnIndex("incoming")));
        message.put("contact_id", res.getString(res.getColumnIndex("contact_id")));
        message.put("contact_name", res.getString(res.getColumnIndex("contact_name")));
        message.put("message", res.getString(res.getColumnIndex("message")));
        message.put("sent", res.getString(res.getColumnIndex("sent")));
        res.moveToNext();
    }
    return message;
}

As I said, this works perfectly - does exactly what I want. I'm just trying to see if there may be a more efficient approach.
 
Back
Top Bottom