MySQL 8.0 引入了窗口函数(Window Functions),这些函数允许你在一组相关行上进行复杂的计算,同时保留每一行的原始数据。窗口函数在数据分析和报表生成中非常有用。以下是一些常见的窗口函数及其使用示例。
1. ROW_NUMBER()
ROW_NUMBER()
函数为每个分区内的行分配一个唯一的序号。
示例
假设我们有一个 sales
表,记录了每个产品的每天销售额:
CREATE TABLE sales (
id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(50),
sale_date DATE,
quantity INT,
price DECIMAL(10, 2)
);
INSERT INTO sales (product_name, sale_date, quantity, price) VALUES
('Product A', '2023-10-01', 2, 100.00),
('Product A', '2023-10-02', 3, 200.00),
('Product A', '2023-10-03', 1, 150.00),
('Product B', '2023-10-01', 1, 150.00),
('Product B', '2023-10-02', 2, 100.00),
('Product B', '2023-10-03', 3, 250.00);
计算每个产品每天的行号:
SELECT
product_name,
sale_date,
quantity,
price,
ROW_NUMBER() OVER (PARTITION BY product_name ORDER BY sale_date) AS row_num
FROM
sales
ORDER BY
product_name,
sale_date;
2. RANK()
RANK()
函数为每个分区内的行分配一个排名,如果有并列的行,排名会跳过相应的数字。
示例
计算每个产品每天的销售额排名:
SELECT
product_name,
sale_date,
quantity,
price,
RANK() OVER (PARTITION BY product_name ORDER BY price DESC) AS rank_num
FROM
sales
ORDER BY
product_name,
sale_date;
3. DENSE_RANK()
DENSE_RANK()
函数类似于 RANK()
,但它不会跳过排名。
示例
计算每个产品每天的销售额密集排名:
SELECT
product_name,
sale_date,
quantity,
price,
DENSE_RANK() OVER (PARTITION BY product_name ORDER BY price DESC) AS dense_rank_num
FROM
sales
ORDER BY
product_name,
sale_date;
4. LEAD()
和 LAG()
LEAD()
和 LAG()
函数用于访问当前行之后或之前的行的数据。
示例
计算每个产品每天的前一日销售额:
SELECT
product_name,
sale_date,
quantity,
price,
LAG(price) OVER (PARTITION BY product_name ORDER BY sale_date) AS previous_day_price
FROM
sales
ORDER BY
product_name,
sale_date;
5. SUM()
SUM()
函数用于计算累计和。
示例
计算每个产品每天的累计销售额:
SELECT
product_name,
sale_date,
quantity,
price,
SUM(quantity * price) OVER (PARTITION BY product_name ORDER BY sale_date) AS cumulative_sales
FROM
sales
ORDER BY
product_name,
sale_date;
6. AVG()
AVG()
函数用于计算平均值。
示例
计算每个产品每天的滚动平均销售额:
SELECT
product_name,
sale_date,
quantity,
price,
AVG(quantity * price) OVER (PARTITION BY product_name ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS rolling_avg_sales
FROM
sales
ORDER BY
product_name,
sale_date;
7. MIN()
和 MAX()
MIN()
和 MAX()
函数用于计算最小值和最大值。
示例
计算每个产品每天的最大销售额:
SELECT
product_name,
sale_date,
quantity,
price,
MAX(price) OVER (PARTITION BY product_name ORDER BY sale_date) AS max_sales
FROM
sales
ORDER BY
product_name,
sale_date;
8. NTILE()
NTILE()
函数将分区内的行分成指定数量的桶。
示例
将每个产品的销售记录分成3个桶:
SELECT
product_name,
sale_date,
quantity,
price,
NTILE(3) OVER (PARTITION BY product_name ORDER BY sale_date) AS ntile_num
FROM
sales
ORDER BY
product_name,
sale_date;
总结
窗口函数在MySQL 8.0中提供了强大的数据分析能力。通过这些函数,你可以在一组相关行上进行复杂的计算,同时保留每一行的原始数据。