關鍵字:mysql實現開窗函數、Mysql實現分析函數、利用變量實現窗口函數
適用范圍:mysql5.7及以下版本,mysql8.0+ 可以直接使用窗口函數
注意,變量是從左到右順序執行的
-- 測試數據
CREATE TABLE `tem` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`str` char(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ;
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (1, 'A');
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (2, 'B');
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (3, 'A');
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (4, 'C');
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (5, 'A');
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (6, 'C');
INSERT INTO `test`.`tem`(`id`, `str`) VALUES (7, 'B');
【1】row_number() over(order by )
變量會最后再計算,所以是先排序好之后,才會開始計算@num
SELECT @num := @num+1 num, id, str FROM tem, (SELECT @str := '', @num := 0) t1 ORDER BY str, id;

【2】實現分組排名效果(row_number() over(partition by order by ))
--變量方式
SELECT @num := IF(@str = str, @num + 1, 1) num, id, @str := str str FROM tem, (SELECT @str := '', @num := 0) t1 ORDER BY str, id;

--子查詢方式【取分組中前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); -- 根據成績,求出每個科目的前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;
-- 查詢結果【左邊】原表內容 【右邊】需求結果,根據成績,求出每個科目的前2名
【3】實現dense_rank() over(order by)
--變量會最后再計算,所以是先排序好之后,才會開始計算@num
select id,@num:=IF(@STR=STR,@num,@num+1) rn,@str:=str str from tem t1,(select @str:='',@num:=0) t2 order by str
--

---case when 形式,但該方法在mysql5.5中,只支持非0數字排序生成,字符會有大問題(任意字符被case when 'a' then else end,都會走else)
--且,賦值語句等於0時也為假
--錯誤的方式 select id,str, case when @str=str then @num when @str:=str then @num:=@num+1 end as 'rn' from tem t1,(select @str:='',@num:=1) t2 order by str

--正確的方式 select id,str, case when @str=str then @num when @str:=str then @num:=@num+1 else @num:=@num+1 end as 'rn' from tem t1,(select @str:='',@num:=0) t2 order by str
--關於數字的case when 驗證
關於字符、字符串 的case when驗證

【4】rank() over()
---------------------
測試數據代碼大部分引用自:https://blog.csdn.net/mingqing6364/article/details/82621840