1.
通过子查询方式实现(
该方法不可取
)
1.1
先将数据按照日期倒序排序(日期最新的在最前面),然后在group,这样每个分类的第一条肯定是日期最新的。
SELECT *
FROM (SELECT *
FROM test
WHERE created_time BETWEEN '2018-09-11 00:00:00' AND '2018-09-11 23:59:59'
ORDER BY `created_time` DESC) `tmp`
GROUP BY category
ORDER BY `created_time` DESC
#有问题。这里分组取的并不是每个分组中的第一行数据。
#官方文档说明:去掉sql_mode中的
ONLY_FULL_GROUP_BY
mysql可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的,这可能不是您想要的。 此外,通过添加ORDER BY子句不能影响从每个组中选择值。 选择值之后,将进行结果集排序,并且ORDER BY不会影响服务器在每个组中选择哪个值。
1.2 对于自增id来说:
一般id越大的时间越近,可以先选出各个分类最大的id,然后in。
SELECT *
FROM test
WHERE id IN (SELECT MAX(id) FROM test GROUP BY category_id);
1.3
连表查询,选择出每个分类的id和最大时间作为一个临时表,然后原表和临时表连接,条件是分类id和时间相等。
SELECT *
FROM test AS a, (
SELECT category_id, MAX(DATE) AS `date`
FROM test AS b
GROUP BY category_id) AS b
WHERE a.category_id=b.category_id
AND a.date = b.date
注:1.2 和 1.3 方法最可靠
2. 通过group_concat函数
* 利用
group_concat函数的排序功能
group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
作用:将要连接的字段按照排序字段的顺序用分隔符连起来显示,默认分隔符是”,”。
如:select group_concat(id order bydatedesc) fromtestgroup by category_id
按照时间排序将id连接起来,第一个一定是时间最新的
* 利用substring_index函数来截取第一个值
substring_index(str,delim,count),str:要处理的字符串、delim:分隔符、count:计数
GROUP_CONCAT将group by 后的id排序后连接起来,SUBSTRING_INDEX取得每行(每个分类)的第一个。
SELECT *
FROM `test`
WHERE id IN (SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY `date` DESC),',',1)
FROM `test`
GROUP BY category_id )
ORDER BY `date` DESC;
遇到问题:当每个分租的行数比较多,GROUP_CONCAT()的字段又比较长,会报如下错误:
错误代码: 1105
bytes.Buffer: truncation out of range
原因:group_concat有长度限制
解决方法:变量:group_concat_max_len为1024,设置的大一点
例如:SET SESSION group_concat_max_len=9999999