如何通过ORDER构造GROUP BY SQLite查询?

我有一个相当有趣的情况。 我有一个SQLite数据库充满地址和消息(地址不唯一;消息)。 每封邮件也有一个与之相关的date。 我想要做的是select第一条消息的地址,消息,date以及与该地址关联的消息数量。

所以,我想,“我只能按地址分组,每个地址只能得到一个消息,然后按datesorting,并取得地址列的COUNT。

我做到了,它的工作…有点。 它获取正确的计数,每个地址只提取一条消息,并按datesorting – 但不会为地址select最近的消息。 这似乎是任意的。

作为一个例子,我从地址Y有三条消息(最早到最近)A,B,C和地址Z三条消息D,E,F。查询可以获取消息B和E, 然后按date对它们进行sorting。 它应该获取消息C和F,并按datesorting。

这是我到目前为止:

// Expanded version: Cursor cursor = db.query( /* FROM */ "messages_database", /* SELECT */ new String[]{ "*", "COUNT(address) AS count" }, /* WHERE */ null, /* WHERE args */ null, /* GROUP BY */ "address", /* HAVING */ null, /* ORDER BY */ "date DESC" ); // Or, same code on one line: Cursor cursor = db.query("messages_database", new String[]{ "*", "COUNT(address) AS count" }, null, null, "address", null, "date DESC"); 

我觉得这可能与HAVING条款有关,但我真的不知道。 我已经使用MySQL很多与PHP,但从来没有HAVING之前。 我尝试设置我的HAVING子句为"MAX(date)" ,但它没有效果。 如果我将GROUP BY子句设置为"address, date" ,那么它们按datesorting,但当然它们都是单独的,而不是分组(因为date不同)。

谷歌search已经certificate是徒劳的; 像“ androidsqlite订单之前组 ”和“ 按订单的android的sqlite组 ”的查询产生没有相关的结果。

我怎样才能不删除我的GROUP子句(因为COUNT()依赖于此)为每个地址select一个最新的消息? 我需要两个查询吗?

编辑 :基于@阿德里安在评论中与我联系的答案 ,我想出了两个查询都产生了相同的结果; 一行,其中计数是7(这是地址的总数,而不是每个地址的消息),并且显示的地址不是最新消息的地址。

这两个查询是:

 Cursor cursor = db.rawQuery( "SELECT t.*, COUNT(t.message_content) AS count " + "FROM messages_database t " + "INNER JOIN (" + " SELECT address, MAX(date) AS maxdate " + " FROM messages_database " + " GROUP BY address " + ") ss ON t.address = ss.address AND t.date = ss.maxdate", null ); Cursor cursor = db.rawQuery( "SELECT t1.*, COUNT(t1.message_content) AS count " + "FROM messages_database t1 " + "LEFT OUTER JOIN messages_database t2 " + "ON (t1.address = t2.address AND t1.date < t2.date) " + "WHERE t2.address IS NULL", null ); 

Solutions Collecting From Web of "如何通过ORDER构造GROUP BY SQLite查询?"

SQLite有一个扩展,使得最大的每组问题变得更容易:
如果您正在使用MAX()MIN()聚合函数,并且如果您同时select其他列而不在聚合函数中使用它们或按它们进行分组,则保证这些列的结果值出来具有最大值/最小值的相同logging。 (这在其他SQL方言中是不允许的,并在SQLite 3.7.11中引入。)

所以,对于你的问题,你可以使用这样的查询:

 SELECT *, COUNT(address) AS count, MAX(date) FROM messages_database GROUP BY address 

如果您没有SQLite 3.7.11(可能在大多数Android版本上)或使用其他SQL引擎,则以下查询将起作用:

 SELECT *, (SELECT COUNT(address) AS count FROM messages_database m2 WHERE m1.address = m2.address) FROM messages_database m1 WHERE date = (SELECT MAX(date) FROM messages_database m3 WHERE m1.address = m3.address) GROUP BY address 

解决了! 我结束了使用@CL的组合。 我的方法和我编辑的文章中列出的方法(在这个答案中澄清,由@Adrian发布)。

因为我不想使用3个SELECT语句(就像@ CL。的回答所描述的那样),所以在保留他的方法的同时,我使用了与其他语句相同的INNER JOIN概念。

结果是这样的:

 Cursor cursor = db.rawQuery( "SELECT t.*, ss.count AS count " + "FROM messages_database t " + "INNER JOIN (" + " SELECT address, MAX(date) AS maxdate, COUNT(address) AS count " + " FROM messages_database " + " GROUP BY address " + ") ss ON t.address = ss.address AND t.date = ss.maxdate " + "GROUP BY t.address " + "ORDER BY t.date DESC ", null ); 

它的工作完美!