tft每日頭條

 > 圖文

 > mysql loop用法

mysql loop用法

圖文 更新时间:2025-02-04 14:57:50

關注我「程序猿集錦」,獲取更多分享。

  • 背景
  • 準備實驗環境
    • 準備建表語句
    • 初始化數據
  • 分組排序
  • 分組求和
  • 分組求最大值
背景

在SQL中我們經常遇到一種需求:分組排序,分組求和等各種需求。像這樣的需求,如果在Oracle、SQLserver、postgresql等數據庫中很容易實現,一個開窗函數row_nubmer() over(partition by xxx,yyy order by zzz)就可以解決。

但是在MySQL8.0版本之前,是沒有這樣的開窗函數的。好在8.0之後的版本已經内置了開窗函數。不必自己寫實現邏輯了。但是我們目前還有很多人在使用5.7版本。那麼在5.7版本中,如何實現開窗函數的功能呢?

準備實驗環境準備建表語句

CREATE TABLE `emp` ( `id` int(11) NOT NULL, `emp_name` varchar(255) DEFAULT NULL, `dept_no` varchar(255) DEFAULT NULL, `emp_salary` int(10) DEFAULT NULL, `emp_hire_date` date DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

初始化數據

INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (1, '張三', '0001', 5000, '2017-01-11'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (2, '李四', '0002', 1000, '2018-10-10'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (3, '王五', '0003', 2000, '2018-12-19'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (4, '趙六', '0002', 4000, '2019-09-11'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (5, '王強強', '0001', 3000, '2019-03-14'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (6, '劉陽', '0002', 6000, '2019-08-08'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (7, '周心怡', '0003', 500, '2015-06-10'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (8, '毛志宇', '0004', 4500, '2016-09-20'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (9, '劉德仁', '0002', 3500, '2016-02-25'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (10, '範德武', '0001', 3000, '2020-02-12'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (11, '梅婷婷', '0005', 8000, '2013-07-07'); INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (12, '鄭冰', '0005', 1000, '2014-11-17');

最後的環境如下:

mysql loop用法(MySQL5.7中的開窗函數)1

分組排序

需求描述:獲取每一個部門薪水最高的員工的信息。

需求分析:

  1. 按照部門分組,每一部門的員工放在一組,然後基于這個組中的數據,按照工資降序排列。
  2. 然後再根據排序後的結果集,獲取排序為1的數據行即為結果。
  • 步驟1的SQL如下:定義兩個變量,row_num_t用于存儲每一個組中的排序結果。dept_no_t用于存儲判斷數據行是否是同一組。同事給他們分别初始化數據。然後再查詢的字段當中,先判斷一下當前是否和上一行的部門編号是同一個部門編号。如果是同一個部門編号,則将排序結果字段加1;如果不是同個部門編号,表示要切換為新的組了,這個時候,把排序結果字段重置為1。

select case when @dept_no_t != x.dept_no then @row_num_t := 1 else @row_num_t := @row_num_t 1 end as sort_result, x.id, x.emp_name, -- x.dept_no, @dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x, (select @dept_no_t := '') as t1, (select @row_num_t := 0) as t2 order by dept_no, emp_salary desc;

  • 步驟1的示例結果如下:

mysql loop用法(MySQL5.7中的開窗函數)2

  • 步驟2的SQL語句如下:在步驟1的SQL基礎之上,在外出包裹一層查詢,然後時候用where條件獲取上面内層查詢結果中排序為1的數據行。

select * from ( select case when @dept_no_t != x.dept_no then @row_num_t := 1 else @row_num_t := @row_num_t 1 end as sort_result, x.id, x.emp_name, -- x.dept_no, @dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x, (select @dept_no_t := '') as t1, (select @row_num_t := 0) as t2 order by dept_no, emp_salary desc ) as y where y.sort_result = 1;

  • 步驟2的示例結果如下:

mysql loop用法(MySQL5.7中的開窗函數)3

分組求和

需求描述:累計統計每一個部門下所有員工的工資之和。

分析:按照部門分組,每一部門的員工放在一組,然後基于這個組中的數據,逐行累加該部門下所有員工的工資。

  • SQL如下:定義一個用于存儲最後每組員工工資之和的變量emp_salary_sum_t,然後再每一行數據是否為同一組數據,如果是同一組數據,則将這行數據的工資,累加到工資之和的變量中;如果不是同一組數據,把當前行的工資賦值給每組工資之和的變量。

select case when @dept_no_t != x.dept_no then @row_num_t := 1 else @row_num_t := @row_num_t 1 end as sort_result, case when @dept_no_t != x.dept_no then @emp_salary_sum_t := x.emp_salary when @dept_no_t = x.dept_no then @emp_salary_sum_t := @emp_salary_sum_t x.emp_salary end as emp_salary_sum, x.id, x.emp_name, -- x.dept_no, @dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x, (select @dept_no_t := '') as t1, (select @row_num_t := 0) as t2, (select @emp_salary_sum_t := 0) as t3 order by dept_no, emp_salary desc;

  • 最後的示例結果如下:

mysql loop用法(MySQL5.7中的開窗函數)4

分組求最大值

需求描述:計算每個員工和部門中工資最高員工的工資差。

需求分析:

  1. 根據員工的部門分組,然後判斷得到每組數據中,工資最高的員工的工資。把這個作為一個新列查詢出出來。
  2. 基于步驟1的結果集中的新列,和員工的工資列做減法得到差值。
  • 步驟1SQL語句如下:

select case when @dept_no_t != x.dept_no then @emp_salary_max_t := x.emp_salary when @dept_no_t = x.dept_no and x.emp_salary > @emp_salary_max_t then @emp_salary_max_t := x.emp_salary else @emp_salary_max_t end as emp_salary_max, x.id, x.emp_name, @dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x, (select @dept_no_t := '') as t1, (select @emp_salary_max_t := 0) as t4 order by dept_no, emp_salary desc

  • 步驟1實驗結果如下:

mysql loop用法(MySQL5.7中的開窗函數)5

  • 步驟2SQL語句如下:

select y.emp_salary_max, y.emp_salary_max - y.emp_salary as cha, y.id, y.emp_name, y.dept_no, y.emp_salary, y.emp_hire_date from ( select case when @dept_no_t != x.dept_no then @emp_salary_max_t := x.emp_salary when @dept_no_t = x.dept_no and x.emp_salary > @emp_salary_max_t then @emp_salary_max_t := x.emp_salary else @emp_salary_max_t end as emp_salary_max, x.id, x.emp_name, @dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x, (select @dept_no_t := '') as t1, (select @emp_salary_max_t := 0) as t4 order by dept_no, emp_salary desc ) as y;

  • 步驟2實驗結果如下:

mysql loop用法(MySQL5.7中的開窗函數)6

以上就是MySQL5.7版本中,如何使用開窗函數的示例。希望能這篇文章能夠幫到你,也歡迎你把文章分享給更多的朋友。如果有什麼問題請留言,我看到後會第一時間回複你。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved