mysql的 函数 group_concat , substring_index 的使用以及 分库分表操作

本文介绍了如何在MySQL中通过group_concat、substr等函数处理分组聚合查询,以实现类似Oracle和PostgreSQL的OVER(PARTITION BY)功能,包括查找每个用户的最近一笔消费金额、过去10个登陆IP等业务需求。

转载: http://www.tuicool.com/articles/eQ3EVv


mysql中没有类似oracle和postgreSQL的 OVER(PARTITION BY)功能. 那么如何在MYSQL中搞定分组聚合的查询呢

先说结论: 利用 group_concat + substr等函数处理

例如: 订单表一张, 只保留关键字段

id user_id money create_time
1 1 50 1420520000
2 1 100 1420520010
3 2 100 1420520020
4 2 200 1420520030

业务: 查找每个用户的最近一笔消费金额

单纯使用group by user_id, 只能按user_id 将money进行聚合, 是无法将最近一单的金额筛选出来的, 只能满足这些需求, 例如: 每个用户的总消费金额 sum(money), 最大消费金额 max(money), 消费次数count(1) 等

但是我们有一个group_concat可以用, 思路如下:

1. 查找出符合条件的记录, 按user_id asc, create_time desc 排序;

select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc
user_id money create_time
1 100 1420520010
1 50 1420520000
2 200 1420520030
2 100 1420520020

2. 将(1)中记录按user_id分组, group_concat(money);

select t.user_id, group_concat( t.money ) moneys from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc) t group by user_id
user_id moneys
1 100,50
2 200,100

3. 这时, 如果用户有多个消费记录, 就会按照时间顺序排列好, 再利用 subString_index 函数进行切分即可

完整SQL:

select t.user_id, substring_index(group_concat( t.money ),',',1) lastest_money from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc) t group by user_id ;
user_id moneys
1 100
2 200

利用这个方案, 以下类似业务需求都可以这么做, 如:

1. 查找每个用户过去10个的登陆IP

2. 查找每个班级中总分最高的两个人

----------- 分割线 ------- :


分库分表操作 :

 见 该文章 :mysql数据库的

http://www.jb51.net/article/36272.htm


MySQL 中,`GROUP_CONCAT()` 是一种用于将多行数据聚合为单个字符串的函数。然而,MySQL 并未提供内置的 `SPLIT()` 函数来作为其反操作。如果需要实现类似于拆分字符串的功能,则可以通过自定义存储过程或使用其他编程语言(如 Python 或 PHP)配合 MySQL 来完成。 以下是几种常见的解决方案: ### 方法一:通过用户变量模拟拆分逻辑 可以利用 MySQL 的用户变量以及字符串处理函数(如 `SUBSTRING_INDEX()` 和循环结构),手动实现字符串拆分的效果。以下是一个简单的例子[^1]: ```sql SET @str = 'apple,banana,cherry'; SET @delim = ','; SELECT SUBSTRING_INDEX(@str, @delim, 1) AS part1, SUBSTRING_INDEX(SUBSTRING_INDEX(@str, @delim, 2), @delim, -1) AS part2, SUBSTRING_INDEX(@str, @delim, -1) AS part3; ``` 上述查询会返回如下结果: | part1 | part2 | part3 | |-------|---------|--------| | apple | banana | cherry | 这种方法适用于固定数量的部分拆分场景,但如果需要动态支持任意长度的列表,则需进一步扩展逻辑。 ### 方法二:创建存储过程进行递归拆分 对于更复杂的业务需求,可能需要编写一个存储过程来进行逐项解析并插入到临时表中保存结果。下面展示了一个基本框架[^1]: ```sql DELIMITER $$ CREATE PROCEDURE SplitString(IN input_string VARCHAR(255), IN delimiter CHAR(1)) BEGIN DECLARE temp_str VARCHAR(255); DECLARE pos INT DEFAULT 1; DROP TEMPORARY TABLE IF EXISTS result_table; CREATE TEMPORARY TABLE result_table (item VARCHAR(255)); WHILE LENGTH(input_string) > 0 DO SET pos = LOCATE(delimiter, input_string); IF pos = 0 THEN INSERT INTO result_table VALUES (input_string); LEAVE WHILE; END IF; SET temp_str = LEFT(input_string, pos - 1); INSERT INTO result_table VALUES (temp_str); SET input_string = MID(input_string, pos + 1); END WHILE; END$$ DELIMITER ; ``` 调用此存储过程后即可获得分割后的每一部分存入名为 `result_table` 的表格里供后续分析使用。 需要注意的是,在实际应用过程中应当考虑边界条件比如空格填充等问题,并确保目标字段宽度足够容纳最大预期值以防截断错误发生。 另外值得注意的一点是当面对非常庞大的数据集时采用这种方式可能会带来性能瓶颈因此建议仅限于小型至中型规模的数据处理场合下运用该技术手段。 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值