mysql的SUBSTRING_INDEX 和GROUP_CONCAT

导读:本篇文章讲解 mysql的SUBSTRING_INDEX 和GROUP_CONCAT,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

问题

今天在做项目中的一个小模块,就是查询所有项目的应收款。

当我拿到这个模块时,并不知道该怎么做?因为刚毕业,没有做过这样的项目,但又不得不做。

幸好出生在这个网络信息纷飞的年代,于是通过谷歌来查询解决方法,最终得出了自己的方法。

所以,当我们拿到自己没有做过的项目,千万不要说不会做,而是通过工具得出解决方案。

应收款放在变更表中,关联到项目财务科目的id。项目财务表存储的对应的是一期、二期、三期等应收款。每一期应收款的金额都会变更,因而,需要将某期最近的金额拿出来,然后再进行sum统计。但凡写的不对,烦请提出。解决问题的思路:

  • 按项目科目的id分组
  • 取出每组当中最新的金额
  • 再进行统计

GROUP_CONCAT

这个时候就用到了GROUP_CONCATGROUP是组,CONCAT合并多个字符串。顾名思义,它的功能是:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。

GROUP_CONCAT( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
[]中的数据表示可用可不用

如果我们没有指定分隔符的话,默认是“,”,比如:

-- 拼接的是变更表的id(用这个id来统计变更表的金额),按照时间的降序排列,以财务科目的id进行分组,
-- 取第一条数据,这是最新的数据,可以看下图
SELECT
	GROUP_CONCAT(
		zmc1.id
		ORDER BY
			zmc1.create_datetime DESC
	) AS 财务科目id对应变更表的id,
	zmc1.financial_subject_id AS 财务科目id
FROM
	zq_money_change zmc1
WHERE
	zmc1.is_deleted = 0
GROUP BY
	zmc1.financial_subject_id;

统计结果:

这里写图片描述

假如,我们不用GROUP_CONCAT进行分组,再看看我们的统计结果:

SELECT
	zmc1.id AS 财务科目id对应变更表的id,
	zmc1.financial_subject_id AS 财务科目id
FROM
	zq_money_change zmc1
WHERE
	zmc1.is_deleted = 0
GROUP BY
	zmc1.financial_subject_id
ORDER BY
	zmc1.create_datetime ASC

这里写图片描述
项目财务科目对应的id有两条,而此时只使用了一条,且还是最旧的一条数据,因而,这不符合我们的需求,所以,需要用GROUP_CONCAT分组后统计。

我们使用“<->”,来看看统计后的数据:

SELECT
	GROUP_CONCAT(
		zmc1.id
		ORDER BY
			zmc1.create_datetime DESC SEPARATOR '<->'
	) AS 财务科目id对应变更表的id,
	zmc1.financial_subject_id AS 财务科目id
FROM
	zq_money_change zmc1
WHERE
	zmc1.is_deleted = 0
GROUP BY
	zmc1.financial_subject_id;

这里写图片描述

SUBSTRING_INDEX

我们按照时间的降序排列,以财务科目的id进行分组,并且拼接好变更表的id,怎么取出字符串中的第一个值?这个值正是我们想要的,比如变更表的中的72这个id。这时,我们就用到了SUBSTRING_INDEX,意思是按照下标截取字符串。

SUBSTRING_INDEX (str,delim,count),str:要处理的字符串、delim:分隔符、count:计数

针对上文的查询结果来看:

  • str:GROUP_CONCAT(zmc1.id ORDER BY zmc1.create_datetime DESC SEPARATOR ‘<->’)
  • delim:<-> 就是str中的分隔符
  • count:1,只取一个数据,比如72

以下的代码可为:

SELECT
	SUBSTRING_INDEX(GROUP_CONCAT(
		zmc1.id
		ORDER BY
			zmc1.create_datetime DESC SEPARATOR '<->'
	),'<->',1) AS 财务科目id对应变更表的id,
	zmc1.financial_subject_id AS 财务科目id
FROM
	zq_money_change zmc1
WHERE
	zmc1.is_deleted = 0
GROUP BY
	zmc1.financial_subject_id;

这里写图片描述

如果,我们把条件改了,会怎么样呢?

这里写图片描述

如果把参数改了,会怎么样呢?

这里写图片描述

结论

-- 应收款
-- 如果变更表的id在上文的临时表中存在,我们就统计改id对应的金额
-- 这也是我为什么拼接变跟表id的原因
-- 需要什么,拼接什么
SELECT
  zmc.new_project AS 每期应收款,
  zmc.financial_subject_id as 财务科目的id,
  zmc.id as 变更表的id
FROM
	zq_money_change zmc
WHERE
	zmc.id IN (
		SELECT
			SUBSTRING_INDEX(
				GROUP_CONCAT(
					zmc1.id
					ORDER BY
						zmc1.create_datetime DESC SEPARATOR '<->'
				),
				'<->',
				2
			) 
		FROM
			zq_money_change zmc1
		WHERE
			zmc1.is_deleted = 0
		GROUP BY
			zmc1.financial_subject_id
	)
AND zmc.create_datetime
ORDER BY
	zmc.id ASC;  

这里写图片描述

这样就好做了,我们可以得到就可以统计每期的金额:

-- 应收款
SELECT
	SUM(zmc.new_project) AS 应付款
FROM
	zq_money_change zmc
WHERE
	zmc.id IN (
		SELECT
			SUBSTRING_INDEX(
				GROUP_CONCAT(
					zmc1.id
					ORDER BY
						zmc1.create_datetime DESC SEPARATOR '<->'
				),
				'<->',
				2
			) 
		FROM
			zq_money_change zmc1
		WHERE
			zmc1.is_deleted = 0
		GROUP BY
			zmc1.financial_subject_id
	)
AND zmc.create_datetime
ORDER BY
	zmc.id ASC;  

这里写图片描述

所以,当我们拿到新的业务时,不要过分的紧张,首先分析该业务涉及到哪些东西,然后再逐步解决难题。

***ps:越努力,越幸运 ***

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99263.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!