demo需求
业务主键相等的情况下 取某主键最新的一条数据,返回列表。
拿几条数据举个例子
标注的不全啊,把代表性的数据标了下,主要就是要红框框中的列表。
方法一 NOT EXISTS
SELECT t.id, t.source_primary_key, t.create_time FROM oydc_data_center t
WHERE NOT EXISTS (
SELECT t2.* FROM `oydc_data_center` t2
WHERE t2.source_primary_key = t.source_primary_key
AND t2.create_time > t.create_time
)
逻辑
主要逻辑就是,当外层每个主键调去匹配的时候,取外层时间大于内层时间存在的数据。这要时间小的数据自然而然过滤掉了。
效果
方法二 join + not in
SELECT t.id, t.source_primary_key, t.create_time FROM oydc_data_center t
WHERE id NOT IN (
SELECT DISTINCT t1.id
FROM oydc_data_center t1
LEFT JOIN oydc_data_center t2
ON t1.source_primary_key = t2.source_primary_key
WHERE t1.create_time < t2.create_time
)
逻辑
先将数据比较小的数据查出来,然后进行排除法,排除掉所有业务主键小的数据,最终就是每个业务主键中时间最新的数据啦。
效果
方法三(计数方式)
SELECT *
FROM (
SELECT t.*, @row_number := IF(@row_source_pk = t.source_primary_key, @row_number+1, 1) AS rk,
@row_source_pk := t.source_primary_key FROM (
SELECT t.* FROM oydc_data_center t
ORDER BY t.source_primary_key, t.create_time DESC, t.id DESC ) t ,
(SELECT @row_number := 0, @row_source_pk := '') c HAVING rk = 1 ) t
ORDER BY t.id
方法四(开窗函数)
demo: 取每学科分数最高的那个。
CREATE TABLE `stu_score` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`stu_name` varchar(30) DEFAULT NULL COMMENT '学生姓名',
`stu_no` varchar(30) DEFAULT NULL COMMENT '学号',
`sub_type` tinyint DEFAULT NULL COMMENT '学科类型',
`score` int DEFAULT NULL COMMENT '学生成绩',
PRIMARY KEY (`id`),
UNIQUE KEY `no_type` (`stu_no`,`sub_type`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生成绩表';
/*Data for the table `stu_score` */
insert into `stu_score`(`id`,`stu_name`,`stu_no`,`sub_type`,`score`) values
(1,'张三','23010101',1,60),
(2,'张三','23010101',2,67),
(3,'李四','23010102',1,54),
(4,'李四','23010102',2,76),
(5,'王五','23010103',1,99),
(6,'赵六','23010104',1,60);
SELECT * FROM (
SELECT *, row_number() over(PARTITION BY sub_type ORDER BY `score` DESC) rk
FROM `stu_score`
)s
WHERE rk = 1
说两句
两种最终的效果都能达到的,但是建议使用第一种,第二种涉及到了表的连接,考虑到性能的话,建议使用第一种好一点。第二种方式不一定用left 也可以用inner。主要目的达到就可以了。
补充
最近用了1 2 两种方式,性能很差。到达10万条数据就顶不住了,又换了一种方式,利用了开窗函数,效果不错。还有一点,记得加上索引。