Mysql中获取分组的最新一条记录
基本原理
SELECT `客户ID`,max(订购日期) from `订单` GROUP BY `客户ID`;
然后在与原始表进行inner join
Note:原始表中,订购日期要增加一个索引。唯一性约束,否则在join的时候,可能会有多余的记录。因为客户`客户ID`,max(订购日期) ;有可能有多个。在原始表中,与本表进行inner join关联的时候,作为连接Key。会出现笛卡尔集的现象。
FAQ:如果这一个列中,唯一性约束,可能需要数据库中的时间列到秒级。然后在所有的值中,不能重复。这个约束要求有点高。实际上,要求是这个组内的约束不能充分就可以,但是暂时无法处理这个约束。
MySQL之group by与max()一起使用的坑 (这个应该是mysql的高级版本,可以group by获取第一条所有信息)g roup by 分组后显示的是第一条记录,而max()取的是相同sid中的最大score值造成的 ,如下
注意:如果mysql的版本支持 any_value。以下的SQL执行没有问题,但是结果有问题
SELECT
INNER JOIN (
SELECT
any_value (`订单ID`) s订单id,
GROUP_CONCAT(订单ID),
max(订购日期)
GROUP BY
`客户ID`
) s ON `订单`.`订单ID` = s.`s订单id`
会出现在一条记录中,any_value的值 ,与分组的客户ID不是同一个记录的可能性。所以在应用中不要使用any_value的方法
设计文档
业务要求
然后以填报明细,进行left join 绩效明细 left join 绩效主表, 形成一张表。然后根据上面的理论,获取到每个绩效明细的最新的一条数据。
然后根据这个数据集,进行 select 绩效主表的id,sum(绩效值)from 绩效主表的id group by 绩效主表的id
把这个值,填入到FR中,进行隐藏。然后在FR中,进行判断
如果填报明细中,没有数据。那么在汇总的时候,就是null。然后转为0
判断的逻辑不在sql语句中实现,在上层逻辑,有报表来进行实现。
考核主表中,采用报表工具计算出来主表的得分值。计算逻辑为
选择考核明细表中的最新一条填报明细。然后与主表进行Join。结果表根据主表的考核ID进行join。如果用户没有填写过,那么汇总值为null,转为0.
在报表逻辑计算该值,
如果 (该汇总值- 计算参考值)>100
按照100来计算权重
如果 <0
按照0来进行计算
如果在[0,100]区间,那么计算的值计算权重
数据ER关系表
数据关系 考核主表 1:n 考核明细表 1:n 填报明细
构造模拟数据
考核主表
考核明细表
考核项目填报明细
在数据库中创建3张表
/*
Navicat MySQL Data Transfer
Source Server : 127.0.0.1
Source Server Version : 80015
Source Host : localhost:3306
Source Database : fr
Target Server Type : MYSQL
Target Server Version : 80015
File Encoding : 65001
Date: 2022-08-20 18:43:53
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for 考核主表
-- ----------------------------
DROP TABLE IF EXISTS `考核主表`;
CREATE TABLE `考核主表` (
`考核ID` int(11) NOT NULL AUTO_INCREMENT,
`权重` int(11) DEFAULT NULL,
`计算参考分数` int(11) DEFAULT NULL,
`汇总得分` int(11) DEFAULT NULL,
PRIMARY KEY (`考核ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of 考核主表
-- ----------------------------
INSERT INTO `考核主表` VALUES ('1', '5', '100', null);
INSERT INTO `考核主表` VALUES ('2', '3', '50', null);
Navicat MySQL Data Transfer
Source Server : 127.0.0.1
Source Server Version : 80015
Source Host : localhost:3306
Source Database : fr
Target Server Type : MYSQL
Target Server Version : 80015
File Encoding : 65001
Date: 2022-08-20 18:44:04
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for 考核明细
-- ----------------------------
DROP TABLE IF EXISTS `考核明细`;
CREATE TABLE `考核明细` (
`考核明细ID` int(11) NOT NULL AUTO_INCREMENT,
`考核内容` varchar(255) DEFAULT NULL,
`考核负责人` varchar(255) DEFAULT NULL,
`考核明细得分` int(11) DEFAULT NULL,
`考核主表ID` int(11) DEFAULT NULL,
PRIMARY KEY (`考核明细ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of 考核明细
-- ----------------------------
INSERT INTO `考核明细` VALUES ('1', 'A', 'sjk', null, '1');
INSERT INTO `考核明细` VALUES ('2', 'B', 'lt', null, '1');
INSERT INTO `考核明细` VALUES ('3', 'C', 'syc', null, '2');
Navicat MySQL Data Transfer
Source Server : 127.0.0.1
Source Server Version : 80015
Source Host : localhost:3306
Source Database : fr
Target Server Type : MYSQL
Target Server Version : 80015
File Encoding : 65001
Date: 2022-08-20 18:44:15
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for 考核项目填报明细
-- ----------------------------
DROP TABLE IF EXISTS `考核项目填报明细`;
CREATE TABLE `考核项目填报明细` (
`填报明细ID` int(11) NOT NULL AUTO_INCREMENT,
`填报时间` datetime DEFAULT NULL,
`奖罚得分` int(11) DEFAULT NULL,
`考核明细ID` int(11) DEFAULT NULL,
PRIMARY KEY (`填报明细ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of 考核项目填报明细
-- ----------------------------
INSERT INTO `考核项目填报明细` VALUES ('1', '2022-08-19 16:30:17', '-10', '1');
INSERT INTO `考核项目填报明细` VALUES ('2', '2022-08-20 16:30:41', '-20', '1');
INSERT INTO `考核项目填报明细` VALUES ('3', '2022-08-16 16:42:22', '-50', '2');
INSERT INTO `考核项目填报明细` VALUES ('4', '2022-08-02 16:42:39', '-70', '2');
创建中间的视图
获取考核填报明细分组的最新一条的表
。针对这个单表操作。约束的条件,是分组中,根据这个分组id及时间为一条。在同一个分组下,时间不能一样。否则在join 的时候,会出现多条记录
SELECT
`a`.`填报明细ID` AS `填报明细ID`,
`a`.`填报时间` AS `填报时间`,
`a`.`奖罚得分` AS `奖罚得分`,
`a`.`考核明细ID` AS `考核明细ID`
`考核项目填报明细` `a`
JOIN (
SELECT
`考核项目填报明细`.`考核明细ID` AS `考核明细ID`,
`考核项目填报明细`.`填报时间`
) AS `填报时间`
`考核项目填报明细`
GROUP BY
`考核项目填报明细`.`考核明细ID`
) `s` ON (
`a`.`考核明细ID` = `s`.`考核明细ID`
AND (
`a`.`填报时间` = `s`.`填报时间`
)
创建汇总表View
SELECT
`考核主表`.`考核ID` AS `考核ID`,
`考核主表`.`权重` AS `权重`,
`考核主表`.`计算参考分数` AS `计算参考分数`,
`考核主表`.`汇总得分` AS `汇总得分`,
`考核明细`.`考核明细ID` AS `考核明细ID`,
`考核明细`.`考核内容` AS `考核内容`,
`考核明细`.`考核负责人` AS `考核负责人`,
`考核明细`.`考核明细得分` AS `考核明细得分`,
`考核项目填报明细最新条目view`.`填报时间` AS `填报时间`,
`考核项目填报明细最新条目view`.`填报明细ID` AS `填报明细ID`,
`考核项目填报明细最新条目view`.`奖罚得分` AS `奖罚得分`
`考核主表`
LEFT JOIN `考核明细` ON (
`考核主表`.`考核ID` = `考核明细`.`考核主表ID`
LEFT JOIN `考核项目填报明细最新条目view` ON (
`考核项目填报明细最新条目view`.`考核明细ID` = `考核明细`.`考核明细ID`
)
计算汇总得分的SQL
SELECT
考核主表.*, s.`奖罚汇总`
`考核主表`
LEFT JOIN (
SELECT
考核ID,
ISNULL(sum(`奖罚得分`)),
sum(`奖罚得分`)