-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
`password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', '1', 18, '[email protected]');
INSERT INTO `user` VALUES (2, 'Jack', '2', 20, '[email protected]');
INSERT INTO `user` VALUES (3, 'Tom', '3', 21, '[email protected]');
INSERT INTO `user` VALUES (4, 'Sandy', '4', 20, '[email protected]');
INSERT INTO `user` VALUES (5, 'Billie', '5', 21, '[email protected]');
SET FOREIGN_KEY_CHECKS = 1;
select u.*
,@rownum :=@rownum+1 rownum
from user u, (select @rownum:=0 , @curValue:=null) r
备注:
1. @rownum和@curVal为自定义的用户变量,仅针对当前客户端有效,此处只用rownum;
2. (select @rownum:=0 , @curValue:=null) r 初始化@rownum和@curVal变量;
(mysql中‘’、0、null均为false);
根据sql的执行顺序可知 变量会最后再计算,所以是先排序好之后,才会开始计算@num
select
@rownum :=@rownum+1 rownum,
u.*
from user u, (select @rownum:=0) r
order by id desc
select
@rownum :=IF(@age=age, @rownum+1, 1) rownum,
@age :=age ageTmp,
u.*
from user u, (select @rownum:=0, @age:=null) r
order by age,id
解释:
1、首先通过对需要分组的字段排序,和按分组后的显示顺序字段排序,获得基本数据
2、因为rownum记录的是每组的顺序值,所以在将rownum赋值值判断age是否为此组的值,不是则重新开始计数
--子查询方式【取分组中前N行(排名前几名)】
mysql 相关子查询参考
select * from testGroup as a
where a.ID in (select ID from testGroup b where a.UserID = b.UserID order by b.OrderID limit 2)
--或者
select * from testGroup a
where not exists (select 1 from testGroup b where a.UserID = b.UserID and a.OrderID > b.OrderID
having count(1) >= 2)
--或者
select * from testGroup a
where (select count(1) from testGroup b where a.UserID = b.UserID and a.ID >= b.ID) <= 2
--没有唯一标识的表,可以用checksum来标识每行(MSSQL?)
select * from testGroup as a
where checksum(*) in (select top 2 checksum(*) from testGroup b where a.UserID = b.UserID order by b.OrderID)
mysql使用子查询实现
create table test1_1(id int auto_increment primary key,`subject` char(20),score int);
insert into test1_1 values(null,'语文',99),(null,'语文',98),(null,'语文',97);
insert into test1_1 values(null,'数学',89),(null,'数学',88),(null,'数学',87);
insert into test1_1 values(null,'英语',79),(null,'英语',78),(null,'英语',77),(null,'英语',78);
-- 根据成绩,求出每个科目的前2名
select * from test1_1;
select * from test1_1 t1
where (select count(1) from test1_1 t2 where t1.subject=t2.subject and t2.score>=t1.score ) <=2;
理解:相当于子查询中所有值分别与t1中的一个值进行比较,t2中score的值大于t1中此值的数量小于2,则代表每组按照分值从大到小取前两名。
rank() over()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内)
dense_rank() over()是连续排序,有两个第二名时仍然跟着第三名。相比之下row_number是没有重复值的 .
分别有分组与不分组排序。只看分组的就可以,上面的数据多加一条 (null,'英语',78) 方便看结果
--变量会最后再计算,所以是先排序好之后,才会开始计算@num
select
CASE
WHEN @str != subject THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS ROW_NUMBER,
CASE
WHEN @str != subject THEN @rank:= 1
WHEN @scoretmp = score THEN @rank
ELSE @rank:= @rownum
END AS RANK,
CASE
WHEN @str != subject THEN @dense_rank:= 1
WHEN @scoretmp = score THEN @dense_rank
ELSE @dense_rank:= @dense_rank + 1
END AS DENSE_RANK,
@str :=subject as subjecttmp,
@scoretemp :=score as scoretemp,
u.*
from sub u,(select @rownum :=0, @rank :=0, @dense_rank :=0, @str :=null, @scoretmp:= 0) r
order by subject,score desc
看着rank和dense_rank的写法没问题,但是此出现的不正确的结果,找到原因再来更改。
--关于数字的case when 验证
关于字符、字符串 的case when验证
SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS ROW_NUMBER,
CASE
WHEN @ke != ke THEN @rank:= 1
WHEN @val = val THEN @rank
ELSE @rank:= @rownum
END AS RANK,
CASE
WHEN @ke != ke THEN @dense_rank:= 1
WHEN @val = val THEN @dense_rank
ELSE @dense_rank:= @dense_rank + 1
END AS DENSE_RANK,
id,
@ke := ke AS ke,
@val := val AS val
FROM
(SELECT @ke:='') k,
(SELECT @val:=0) v,
(SELECT @rownum:=0) r,
(SELECT @rank:=0) r2,
(SELECT @dense_rank:=0) d,
test_rownum main
ORDER BY
ke, val;
参考
https://www.cnblogs.com/gered/p/10430829.html
http://blog.sina.com.cn/s/blog_64e2d33e0101ashr.html