统计需求往往能快速提升一个人对业务的熟知,而统计某个指标,本身也是一种衡量的标准。本质上是观察某个现象的水平,好的坏的,高的低的,看多了做多了就能发现数据有没有问题。
再补充下个人理解的统计要素:
1. 统计的指标;比如常用的按时间来统计,这里的时间就是统计的指标;
2. 统计的要素;比如每一天的人数,消耗的金额等,这里的要素就是汇总人数,汇总金额;
进入正文: 以统计某个时间段内每个用户的交易记录为例。
我们利用每一次记录的交易记录表作为统计的标准。
交易记录表数据结构大致为:
CREATE TABLE `finance_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`uid` int(11) DEFAULT '0' COMMENT '用户ID',
`trade_type` tinyint(1) DEFAULT '0' COMMENT '交易类型 0 充值 1 业务扣款',
`trade_no` varchar(64) DEFAULT NULL COMMENT '交易号',
`origin_amount` decimal(11,4) DEFAULT '0.0000' COMMENT '原金额',
`new_amount` decimal(11,4) DEFAULT '0.0000' COMMENT '新金额',
`trade_time` datetime(3) DEFAULT NULL COMMENT '交易时间',
`create_time` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`update_time` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_trade_no` (`trade_no`)
) ENGINE=InnoDB AUTO_INCREMENT=546 DEFAULT CHARSET=utf8mb4 COMMENT='账户流水';
接下来分析需求,将统计每日流水拆开出来理解就要统计每天每个用户的消耗记录(可能有点生硬)。
针对这种需求,需要有个统计的表数据(区别于上面的明细记录表),
所以我们生成这张统计表就需要考虑统计的标准,是按天还是按小时或是其他;
生成这个统计记录的任务多久触发一次,要查看的是每一天的历史数据是否还要实时数据;
统计之后,如果已经统计出来的金额数据发生变动将要如何处理,是替换还是保持不变;
于是,我们先要定好这个统计表(上面的问题后续再补充解释):
CREATE TABLE `t_finance_daily_statistics` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`uid` int(11) DEFAULT '0' COMMENT '用户ID',
`count_time` date DEFAULT NULL COMMENT '统计时间',
`settle_amount` decimal(11,4) DEFAULT '0.0000' COMMENT '消耗金额',
`account_new_amount` decimal(11,4) DEFAULT '0.0000' COMMENT '现金账户结余',
`expect_income` decimal(11,4) DEFAULT '0.0000' COMMENT '预计收入',
`net_expect_income` decimal(11,4) DEFAULT '0.0000' COMMENT '净收入',
`create_time` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`update_time` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_p_c` (`puid`,`count_time`)
) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=utf8mb4 COMMENT='账户流水日统计数据';
在代码逻辑中遍历每个用户uid,再编辑每一天开始结束时间start, end, 然后在sql中统计每个用户的充值和消耗汇总数据:
sql语句可以这么写:
select trade_type, sum(`settle_amount`) as `sumSettleAmount` from finance_record where puid = ? and trade_time between ? and ? GROUP BY `trade_type`
其中 trade_type 0 的是充值, 1的是消耗扣款
利用Collectors.groupingBy得到map分组;
Map<Integer, List<FinanceRecord>> financeRecordsMap = financeRecords.parallelStream().collect(Collectors.groupingBy(FinanceRecord::getTradeType));
接下来就能够顺利地拿到每一天汇总的充值和消耗数据了,将数据插进汇总表中,大功告成。 至于展示汇总表的需求,就是查表去展示的逻辑了。
明天再分享,谢谢大家!