mysql實現開窗函數、Mysql實現分析函數


關鍵字: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 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM