mysql分组取数
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。
留下评论