mysql group里获取第n个

这是个老生常谈的问题。mysql由于还不支持row_number()这样的聚合函数(sqlserver支持的,微软大法好!),所以只能找变通的方法。

拼接

先把所有值拼成一个长字符串,然后再从这个长字符串中取最前面和最后面的部分,但是这样会有性能问题 需要用到

GROUP_CONCAT

GROUP_CONCAT(DISTINCT expression ORDER BY expression SEPARATOR sep);

DISTINCT子句用于在连接分组之前消除组中的重复值。 ORDER BY子句允许您在连接之前按升序或降序排序值。 默认情况下,它按升序排序值。 如果要按降序对值进行排序,则需要明确指定DESC选项。 SEPARATOR指定在组中的值之间插入的文字值。如果不指定分隔符,则GROUP_CONCAT函数使用逗号(,)作为默认分隔符。 GROUP_CONCAT函数忽略NULL值,如果找不到匹配的行,或者所有参数都为NULL值,则返回NULL。 GROUP_CONCAT函数返回二进制或非二进制字符串,这取决于参数。 默认情况下,返回字符串的最大长度为1024。如果您需要更多的长度,可以通过在SESSION或GLOBAL级别设置group_concat_max_len系统变量来扩展最大长度。

SUBSTRING_INDEX

SUBSTRING_INDEX(string, delimiter, number)

Parameter Description
string Required. The original string
delimiter Required. The delimiter to search for
number Required. The number of times to search for the delimiter. Can be both a positive or negative number. If it is a positive number, this function returns all to the left of the delimiter. If it is a negative number, this function returns all to the right of the delimiter.

样例:K线数据按时间拼接

SELECT
  DATE_FORMAT(create_time, '%Y%m%d') times, // 时间格式化
  MAX(price) max_price,    // 最高价
  MIN(price) min_price,    // 最低价
  SUM(num) num,            // 每天数量
  SUBSTRING_INDEX(GROUP_CONCAT(CAST(price AS CHAR) ORDER BY create_time asc), ',', 1 ) first_price, 
  SUBSTRING_INDEX(GROUP_CONCAT(CAST(price AS CHAR) ORDER BY create_time DESC), ',', 1 ) last_price
FROM `bill`
GROUP BY `times` // 时间分组

其它

ONLY_FULL_GROUP_BY

在mysql 5.7及以上版本默认增加了一个ONLY_FULL_GROUP_BY的sql_mode。 即SQL 标准中不允许 SELECT 列表,HAVING 条件语句,或 ORDER BY 语句中出现 GROUP BY 中未列表的可聚合列。

https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

ONLY_FULL_GROUP_BY可以关闭,但不建议。因为关闭之后的group_by和使用 ANY_VALUE()的行为是一样的,并不是想象中的选择第一条记录。为了避免不确定性,还是尽量使用严格的sql。

标签:

更新时间:

留下评论