HAVING 与 WHERE 的区别
WHERE关键字在数据分组前对记录进行过滤,不可与聚合函数一起使用。HAVING关键字在数据分组后过滤分组,常与聚合函数一起使用。
教程
https://blog.csdn.net/m0_53022813/category_11649913.html
更新表语句解析
导出所有创建索引的语句
SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` ', 'MODIFY COLUMN `', COLUMN_NAME, '` ',
IF(UPPER(DATA_TYPE) = 'INT', REPLACE(SUBSTRING_INDEX(UPPER(COLUMN_TYPE), ')', 1), 'INT', 'INTEGER'),
UPPER(COLUMN_TYPE)), ') UNSIGNED NOT NULL AUTO_INCREMENT;')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'rz_gs'
AND EXTRA = UPPER('AUTO_INCREMENT')
ORDER BY TABLE_NAME ASC;
更多参考
https://blog.csdn.net/weixin_28702147/article/details/113608711
从某个表中导出部分数据
新建表tmp_export,使用insert和select将指定数据写入,然后导出tmp_export表
insert into tmp_export(a, b, c) (select a, b, c from table_a where a = 'xxx');
导出数据到文件
SELECT a, b, a+b INTO OUTFILE '/tmp/result.text' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table;
使用带条件的mysqldump
mysqldump -u root -p bbscs6 BBSCS_USERINFO –where "id > 123" > test.sql
select语句各子句执行顺序
DROP TABLE IF EXISTS student;
create table student
(
sid int primary key,
name varchar(64),
class char(3)
);
insert into student values (1, '张三', '091');
insert into student values (2, '李四', '091');
insert into student values (3, '王五', '091');
DROP TABLE IF EXISTS sc;
create table sc
(
sid int,
course varchar(64),
score int,
primary key (sid, course)
);
insert into sc values (1, '语文', 80);
insert into sc values (1, '数学', 90);
insert into sc values (1, '英语', 70);
insert into sc values (2, '语文', 60);
insert into sc values (2, '数学', 80);
insert into sc values (2, '英语', 50);
insert into sc values (3, '语文', 100);
insert into sc values (3, '数学', 100);
insert into sc values (3, '英语', 80);
SELECT `s`.`sid`, `s`.`class`, `s`.`name`, -- 6
SUM(`sc`.`score`) AS `total` -- 4
FROM `student` AS `s` LEFT JOIN `sc` -- 1
ON `s`.`sid` = `sc`.`sid`
WHERE `s`.`class` = '091' -- 2
GROUP BY `s`.`sid` -- 3
HAVING MIN(`sc`.`score`) >= 60 -- 5
ORDER BY `total` DESC -- 7
LIMIT 1 OFFSET 1; -- 8
-- sid class name total
-- 1 091 张三 240
-- 该sql在sql_mode=only_full_group_by时无法执行
Error
SELECT a.fund_id, a.price_date FROM `pvn_nav` a where a.isvalid = 1 and fund_id = 'HF00000008' group by a.fund_id, a.price_date HAVING(fund_id) > 1
SELECT a.fund_id, a.price_date FROM `pvn_nav` a where a.isvalid = 1 and fund_id = 'HF00000008' group by a.fund_id, a.price_date HAVING(fund_id) > 'HF00000007'
-- HAVING(fund_id) > 1 实质上是 HAVING fund_id > 1,而'HF00000007'与1判断非假
select 1 = "H1"; -- 0
select 1 > "H1"; -- 1
select 1 < "H1"; -- 0
select 1 = "1"; -- 1
select 1 > "1"; -- 0
select 1 < "1"; -- 0
-- 正确sql如下
SELECT a.fund_id, a.price_date FROM `pvn_nav` a where a.isvalid = 1 and fund_id = 'HF00000008' group by a.fund_id, a.price_date HAVING c(fund_id) > 1
一步一步优化SQL
https://blog.csdn.net/m0_53022813/article/details/124372805
https://blog.csdn.net/weigeshikebi/article/details/80214965
select语句解析
https://dev.mysql.com/doc/refman/8.2/en/select.html
https://www.cnblogs.com/kangxinxin/p/11585935.html
https://blog.csdn.net/qq_29380733/article/details/86291961
创建用户
'canal'@'%'
'user'@'host'
显示数据库
show databases;
创建数据库
create database if not exists sqlexercise charset utf8mb4 collate utf8mb4_general_ci;
查看当前使用数据库
select database();
使用sqlexercise数据库
use sqlexercise;
显示数据库创建信息
show create database sqlexercise;
创建部门表、职员表、职位表、工资表
-- 部门表
drop table sqlexercise.department;
create table if not exists department(
did numeric(4),
dname varchar(20),
dlocation varchar(20),
primary key(did)
);
-- 职员表
drop table sqlexercise.staff;
create table if not exists staff(
id int auto_increment,
sid int(4),
sname varchar(20),
sex numeric(1) not null comment '0:未知 1:男 2:女',
did numeric(4),
leader numeric(4),
hiredate datetime,
primary key(id),
UNIQUE INDEX uidx_sid(sid ASC),
INDEX idx_sname(sname ASC),
INDEX idx_did_leader(did,leader)
);
-- 职员备注表
drop table sqlexercise.staff_note;
create table if not exists staff_note(
id int auto_increment,
sid int(4),
note json,
primary key(id),
UNIQUE INDEX uidx_sid(sid ASC),
);
/*
{
"lucky_day": "星期五",
"birthstone": "蓝宝石",
"sports": {
"team_sports": ["足球", "篮球"],
"individual_sports": ["游泳", "跑步"]
},
"interests": {
"arts": ["绘画", "雕塑"],
"music": ["古典音乐", "爵士乐"],
"literature": ["小说", "诗歌"],
"travel_destinations": ["巴黎", "东京"],
"cuisines": ["意大利菜", "日本料理"],
"technology": ["人工智能", "虚拟现实"]
},
"aversions": {
"places": ["拥挤的市场", "嘈杂的夜店"],
"foods": ["榴莲", "蓝纹奶酪"]
}
}
*/
-- 职位表
drop table sqlexercise.job;
create table if not exists job(
jid numeric(4),
jname varchar(20),
propost varchar(20),
lowsalary numeric(7,2),
highsalary numeric(7,2),
primary key(jid)
);
-- 工资表
drop table sqlexercise.salary;
create table if not exists salary(
sid numeric(4),
jid numeric(4),
basesalary numeric(7,2),
allowance numeric(7,2),
primary key(sid,jid)
);
插入数据
# 以下j
# 部门表数据
insert into sqlexercise.department value(4101,'行政部','北京');
insert into sqlexercise.department value(4102,'人事部','北京');
insert into sqlexercise.department value(4103,'财务部','北京');
insert into sqlexercise.department value(4104,'产品部','上海');
insert into sqlexercise.department value(4105,'运营部','上海');
insert into sqlexercise.department value(4106,'研发部','南京');
# 职员表数据
insert into sqlexercise.staff value(1,2301,'李乐天',1,4101,null,'2000-04-10 17:27:25'); -- 行政总监
insert into sqlexercise.staff value(2,2302,'汪慕蕊',2,4102,null,'2001-05-08 08:12:32'); -- 人事总监
insert into sqlexercise.staff value(3,2303,'龙芳蔼',2,4103,null,'2005-09-12 09:00:23'); -- 财务总监
insert into sqlexercise.staff value(4,2304,'宁明志',1,4104,null,'2000-02-28 08:53:01'); -- 产品总监
insert into sqlexercise.staff value(5,2305,'庄诗珊',2,4105,null,'2007-11-18 16:42:23'); -- 运营总监
insert into sqlexercise.staff value(6,2306,'边英豪',1,4106,null,'2002-03-28 08:10:59'); -- 研发总监
insert into sqlexercise.staff value(7,2307,'相昂然',1,4101,2301,'2004-02-11 08:12:24'); -- 行政经理
insert into sqlexercise.staff value(8,2308,'谭青木',2,4101,2307,'2003-09-30 16:00:05'); -- 行政专员
insert into sqlexercise.staff value(9,2309,'魏宇文',1,4101,2307,'2012-11-05 11:23:01'); -- 行政专员
insert into sqlexercise.staff value(10,2310,'温夏烟',2,4102,2302,'2001-02-14 08:45:21'); -- 人事经理
insert into sqlexercise.staff value(11,2311,'冀莺莺',2,4102,2310,'2012-03-24 16:56:34'); -- 人事主管
insert into sqlexercise.staff value(12,2312,'步星宇',1,4102,2310,'2006-02-23 08:36:20'); -- 人事主管
insert into sqlexercise.staff value(13,2313,'聂景龙',1,4102,2311,'2022-01-13 08:59:59'); -- 人事专员
insert into sqlexercise.staff value(14,2314,'石弘博',1,4102,2311,'2013-04-09 10:34:48'); -- 人事专员
insert into sqlexercise.staff value(15,2315,'晏瑾瑶',2,4102,2312,'2014-01-31 17:12:12'); -- 人事专员
insert into sqlexercise.staff value(16,2316,'叶曼安',2,4102,2312,'2018-07-29 08:56:02'); -- 人事专员
insert into sqlexercise.staff value(17,2317,'孔珍丽',2,4103,2303,'2002-02-12 09:42:31'); -- 财务经理
insert into sqlexercise.staff value(18,2318,'潘博',1,4103,2317,'2004-07-21 08:42:32'); -- 财务专员
insert into sqlexercise.staff value(19,2319,'戴仑',1,4103,2317,'2010-03-06 15:36:00'); -- 财务专员
insert into sqlexercise.staff value(20,2320,'阎浩气',1,4104,2304,'2009-02-11 10:24:14'); -- 产品经理
insert into sqlexercise.staff value(21,2321,'王学义',1,4104,2320,'2001-08-19 14:23:46'); -- 产品专员
insert into sqlexercise.staff value(22,2322,'吕修贤',1,4104,2320,'2002-05-31 10:48:59'); -- 产品专员
insert into sqlexercise.staff value(23,2323,'钟沈静',2,4105,2305,'2006-02-15 11:36:41'); -- 运营经理
insert into sqlexercise.staff value(24,2324,'林梦泽',2,4105,2323,'2016-01-12 11:00:01'); -- 运营专员
insert into sqlexercise.staff value(25,2325,'龙良平',1,4105,2323,'2015-07-12 08:05:03'); -- 运营专员
insert into sqlexercise.staff value(26,2326,'范德润',1,4106,2306,'2009-02-11 15:36:56'); -- 架构师
insert into sqlexercise.staff value(27,2327,'曾修平',1,4106,2326,'2005-04-06 09:23:00'); -- 开发工程师
insert into sqlexercise.staff value(28,2328,'薛依霜',2,4106,2326,'2016-03-17 08:52:01'); -- 测试工程师
insert into sqlexercise.staff value(29,2329,'范兴昌',1,4106,2326,'2021-02-28 08:45:20'); -- 运维工程师
insert into sqlexercise.staff value(30,2330,'谷永寿',1,4106,2326,'2016-03-03 09:00:09'); -- DBA
# 职位表数据
insert into sqlexercise.job value(1101,'行政总监','总监',12000.00,30000.00); -- 行政总监
insert into sqlexercise.job value(1102,'人事总监','总监',12000.00,30000.00); -- 人事总监
insert into sqlexercise.job value(1103,'财务总监','总监',12000.00,30000.00); -- 财务总监
insert into sqlexercise.job value(1104,'产品总监','总监',15000.00,35000.00); -- 产品总监
insert into sqlexercise.job value(1105,'运营总监','总监',15000.00,35000.00); -- 运营总监
insert into sqlexercise.job value(1106,'研发总监','总监',20000.00,40000.00); -- 研发总监
insert into sqlexercise.job value(1107,'行政经理','经理',6000.00,15000.00); -- 行政经理
insert into sqlexercise.job value(1108,'行政专员','专员',3000.00,8000.00); -- 行政专员
insert into sqlexercise.job value(1109,'人事经理','经理',6000.00,15000.00); -- 人事经理
insert into sqlexercise.job value(1110,'人事主管','主管',6000.00,15000.00); -- 人事主管
insert into sqlexercise.job value(1111,'人事专员','专员',3000.00,8000.00); -- 人事专员
insert into sqlexercise.job value(1112,'财务经理','经理',6000.00,15000.00); -- 财务经理
insert into sqlexercise.job value(1113,'财务专员','专员',3000.00,8000.00); -- 财务专员
insert into sqlexercise.job value(1114,'产品经理','经理',8000.00,20000.00); -- 产品经理
insert into sqlexercise.job value(1115,'产品专员','专员',5000.00,10000.00); -- 产品专员
insert into sqlexercise.job value(1116,'运营经理','经理',8000.00,20000.00); -- 运营经理
insert into sqlexercise.job value(1117,'运营专员','专员',5000.00,10000.00); -- 运营专员
insert into sqlexercise.job value(1118,'架构师','经理',10000.00,30000.00); -- 架构师
insert into sqlexercise.job value(1119,'开发工程师','专员',8000.00,20000.00); -- 开发工程师
insert into sqlexercise.job value(1120,'测试工程师','专员',8000.00,20000.00); -- 测试工程师
insert into sqlexercise.job value(1121,'运维工程师','专员',8000.00,20000.00); -- 运维工程师
insert into sqlexercise.job value(1122,'DBA','专员',8000.00,20000.00); -- DBA
# 职薪表数据
insert into sqlexercise.salary value(2301,1101,25000.00,1000.00);
insert into sqlexercise.salary value(2302,1102,25000.00,2000.00);
insert into sqlexercise.salary value(2303,1103,25000.00,1000.00);
insert into sqlexercise.salary value(2304,1104,27000.00,1000.00);
insert into sqlexercise.salary value(2305,1105,27000.00,1000.00);
insert into sqlexercise.salary value(2306,1106,30000.00,1000.00);
insert into sqlexercise.salary value(2307,1107,10000.00,null);
insert into sqlexercise.salary value(2308,1108,6000.00,null);
insert into sqlexercise.salary value(2309,1108,7000.00,null);
insert into sqlexercise.salary value(2310,1109,11000.00,null);
insert into sqlexercise.salary value(2311,1110,10000.00,null);
insert into sqlexercise.salary value(2312,1110,11000.00,null);
insert into sqlexercise.salary value(2313,1111,6000.00,400.00);
insert into sqlexercise.salary value(2314,1111,7000.00,500.00);
insert into sqlexercise.salary value(2315,1111,6500.00,500.00);
insert into sqlexercise.salary value(2316,1111,8000.00,600.00);
insert into sqlexercise.salary value(2317,1112,12000.00,null);
insert into sqlexercise.salary value(2318,1113,6500.00,null);
insert into sqlexercise.salary value(2319,1113,6500.00,null);
insert into sqlexercise.salary value(2320,1114,13000.00,null);
insert into sqlexercise.salary value(2321,1115,8000.00,null);
insert into sqlexercise.salary value(2322,1115,7000.00,null);
insert into sqlexercise.salary value(2323,1116,14000.00,null);
insert into sqlexercise.salary value(2324,1117,6000.00,null);
insert into sqlexercise.salary value(2325,1117,8000.00,null);
insert into sqlexercise.salary value(2326,1118,22000.00,500.00);
insert into sqlexercise.salary value(2327,1119,15000.00,300.00);
insert into sqlexercise.salary value(2328,1120,17000.00,300.00);
insert into sqlexercise.salary value(2329,1121,15000.00,300.00);
insert into sqlexercise.salary value(2330,1122,16000.00,300.00);
source
清空表
delete from table_name
下面给出本人从其它资料(www.cn-java.com)获得的对常用权限的解释:
全局管理权限:
FILE: 在MySQL服务器上读写文件。
PROCESS: 显示或杀死属于其它用户的服务线程。
RELOAD: 重载访问控制表,刷新日志等。
SHUTDOWN: 关闭MySQL服务。
数据库/数据表/数据列权限:
ALTER: 修改已存在的数据表(例如增加/删除列)和索引。
CREATE: 建立新的数据库或数据表。
DELETE: 删除表的记录。
DROP: 删除数据表或数据库。
INDEX: 建立或删除索引。
INSERT: 增加表的记录。
SELECT: 显示/搜索表的记录。
UPDATE: 修改表中已存在的记录。
特别的权限:
ALL: 允许做任何事(和root一样)。
USAGE: 只允许登录–其它什么也不允许做。
-- 复制表结构和表数据
create table django_migrations_backup select * from django_migrations;
-- 复制表结构
create table django_migrations_backup select * from django_migrations where 1<>1;
-- 表重命名
alter table table1 rename as table2;
-- 修改列id的类型为int unsigned
alter table table1 modify id int unsigned;
-- 修改列id的名字为sid,而且把属性修改为int unsigned
alter table table1 change id sid int unsigned;
19、使用optimize table
对于经常修改的表,容易产生碎片,使在查询数据库时必须读取更多的磁盘块,降低查询性能。具有可变长的表都存在磁盘碎片问题,这个问题对blob数据类型更为突出,因为其尺寸变化非常大。可以通过使用optimize table来整理碎片,保证数据库性能不下降,优化那些受碎片影响的数据表。 optimize table可以用于MyISAM和BDB类型的数据表。实际上任何碎片整理方法都是用mysqldump来转存数据表,然后使用转存后的文件并重新建数据表;
-- 进程列表
show processlist;
-- 变量
show variables;
-- 查看某数据库的所有表
show tables from sqlexercise;
-- 列出表各列信息
show full columns from sqlexercise.django_migrations_backup;
-- 列出表的索引
show index from table;
-- 列出数据库的表状态
show table status from sqlexercise;
-- 显示表的创建语句
show create table sqlexercise.django_migrations_backup;
-- 显示当前时间
show now();
select password('root');
show variables like 'log_error'; -- 查找错误日志文件路径
show variables like 'general_log_file'; -- 查找日志文件路径
show variables like 'slow_query_log_file'; -- 慢查询日志文件路径
show variables like 'log_%'; -- 查看日志状态
describe sqlexercise.user
create database if not exists edu_explore charset utf8mb4 collate utf8mb4_general_ci;
create table edu_student(
id bigint unsigned primary key auto_increment COMMENT 'id',
sno VARCHAR(20) NOT NULL COMMENT '学号',
name VARCHAR(25) COMMENT '姓名',
gender tinyint COMMENT '性别',
age tinyint COMMENT '年龄',
gmt_create datetime COMMENT '创建时间',
gmt_modified datetime COMMENT '修改时间'
);
create table edu_course(
id bigint unsigned primary key auto_increment COMMENT 'id',
cno VARCHAR(20) NOT NULL COMMENT '课程号',
name VARCHAR(25) COMMENT '课程名',
gmt_create datetime COMMENT '创建时间',
gmt_modified datetime COMMENT '修改时间'
);
create table edu_sc(
id bigint unsigned primary key auto_increment COMMENT 'id',
sno VARCHAR(20) NOT NULL COMMENT '学号',
cno VARCHAR(20) NOT NULL COMMENT '课程号',
gmt_create datetime COMMENT '创建时间',
gmt_modified datetime COMMENT '修改时间'
);
# 仅直接配置主键索引
# 性别用int
# 年龄用int
CREATE TABLE `auth_user` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`uid` varchar(3) NOT NULL COMMENT '用户ID',
-- `uid` bigint unsigned NOT NULL COMMENT '用户ID',
`identity_type` tinyint unsigned NOT NULL DEFAULT 1 COMMENT '1用户名 2手机号 3邮箱 4QQ 5微信 6新浪微博',
`identifier` varchar(50) NOT NULL COMMENT '身份标识,手机号、邮箱、用户名或第三方应用的唯一标识',
`certificate` varchar(20) NOT NULL COMMENT '身份凭证',
`gmt_create` datetime COMMENT '创建时间',
`gmt_modified` datetime COMMENT '上次修改时间',
PRIMARY KEY `pk_id` (`id`),
UNIQUE KEY `uk_uid_identity_type` (`uid`,`identity_type`)
-- KEY `idx_uid` (`uid`)
) COMMENT='用户授权表';
销售额
OVER (PARTITION BY)的作用:
OVER (PARTITION BY)通常与其他聚合函数一起使用,如SUM(), AVG(), COUNT(), MAX()和MIN()等。它允许你对数据进行分区(基于某个列的值),然后在每个分区内独立地应用聚合函数。这样,每个行都会保留,并且会添加一个或多个聚合计算的列,这些列是基于每个分区的聚合结果。
GROUP BY与OVER (PARTITION BY)的区别:
- 数据聚合:
GROUP BY用于将数据分组,并为每个组返回一行聚合结果(如总和、平均值等)。而OVER (PARTITION BY)则在保留所有原始数据行的同时,为每个行添加聚合计算的列。 - 执行顺序:
GROUP BY在SELECT之后、ORDER BY之前执行,而PARTITION BY是在所有这些关键字之后执行的,可以简单理解为在执行完SELECT之后,在所得结果集之上进行PARTITION BY分组。 - 结果集影响:使用
GROUP BY后,结果集中的行数会减少,因为每个组只返回一行。而使用OVER (PARTITION BY)后,结果集中的行数不变,每个行都会保留,并添加聚合计算的列。
简单说,partition就是用来实现窗口函数的
示例说明:
假设有一个员工表employee_tbl,包含员工的姓名、日期和登录次数,我们想要计算每个员工的总登录次数,同时保留每个员工的每次登录记录。
使用GROUP BY的示例:
sql
SELECT name, COUNT(*) as total_signins FROM employee_tbl GROUP BY name;
这个查询会返回每个员工的总登录次数,但不会保留每次登录的记录。
使用OVER (PARTITION BY)的示例:
sql
SELECT name, date, signin, SUM(signin) OVER (PARTITION BY name) as total_signins FROM employee_tbl;
这个查询会为每个员工的每次登录记录添加一个total_signins列,显示该员工的总登录次数,同时保留每次登录的记录。
CREATE TABLE tb_order (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_id BIGINT,
sid INT,
sale_date DATE,
price DECIMAL(10, 2)
);
INSERT INTO tb_order (order_id, sid, sale_date, price) VALUES
(1, 101, '2024-01-01', 250.50),
(2, 102, '2024-01-02', 150.75),
(3, 103, '2024-01-03', 375.00),
(4, 104, '2024-01-04', 120.25),
(5, 105, '2024-01-05', 450.00),
(6, 106, '2024-01-06', 230.45),
(7, 107, '2024-01-07', 550.99),
(8, 108, '2024-01-08', 320.00),
(9, 109, '2024-01-09', 199.99),
(10, 110, '2024-01-10', 299.50),
(11, 111, '2024-01-11', 399.99),
(12, 112, '2024-01-12', 249.99),
(13, 113, '2024-01-13', 599.99),
(14, 114, '2024-01-14', 175.00),
(15, 115, '2024-01-15', 450.00),
(16, 116, '2024-01-16', 225.50),
(17, 117, '2024-01-17', 350.00),
(18, 118, '2024-01-18', 275.75),
(19, 119, '2024-01-19', 399.99),
(20, 120, '2024-01-20', 499.99),
(21, 121, '2024-01-21', 125.00),
(22, 122, '2024-01-22', 299.99),
(23, 123, '2024-01-23', 399.99),
(24, 124, '2024-01-24', 249.99),
(25, 125, '2024-01-25', 599.99),
(26, 126, '2024-01-26', 175.00),
(27, 127, '2024-01-27', 450.00),
(28, 128, '2024-01-28', 225.50),
(29, 129, '2024-01-29', 350.00),
(30, 130, '2024-01-30', 275.75);
窗口函数(Window Functions)在SQL中除了进行分区聚合计算外,还有很多其他的用途。以下是一些常见的窗口函数用途:
计算运行总数(Running Totals):
- 使用窗口函数可以计算累积的总和或计数,例如,计算每个月的累积销售额。
SELECT order_date, sales_amount, SUM(sales_amount) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total FROM sales;计算移动平均值(Moving Averages):
- 窗口函数可以用来计算一段时间内的平均值,比如过去7天的平均销售额。
SELECT order_date, sales_amount, AVG(sales_amount) OVER (ORDER BY order_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg FROM sales;排名和位置函数:
- 使用
RANK(),DENSE_RANK(),ROW_NUMBER()等函数,可以对结果集进行排名。
SELECT name, score, RANK() OVER (ORDER BY score DESC) AS rank FROM students;- 使用
比较不同行的数据:
- 窗口函数可以比较同一查询中的不同行,比如计算每个员工相对于团队平均销售额的百分比。
SELECT name, sales_amount, (sales_amount / SUM(sales_amount) OVER ()) * 100 AS percentage_of_total FROM employees;数据的差分计算:
- 计算当前行与前一行或后一行的差值,比如计算销售额的月环比增长。
SELECT order_date, sales_amount, LAG(sales_amount, 1) OVER (ORDER BY order_date) AS previous_month_sales, (sales_amount - LAG(sales_amount, 1) OVER (ORDER BY order_date)) / LAG(sales_amount, 1) OVER (ORDER BY order_date) * 100 AS month_over_month_growth FROM sales;数据的领先和滞后计算:
- 使用
LEAD()和LAG()函数可以访问当前行的前几行或后几行的数据。
SELECT order_date, sales_amount, LEAD(sales_amount, 1) OVER (ORDER BY order_date) AS next_month_sales FROM sales;- 使用
数据的聚合和去重:
- 窗口函数可以用于聚合数据,同时去除重复的行,比如计算每个组的第一条记录。
SELECT name, MIN(order_date) OVER (PARTITION BY name) AS first_order_date FROM orders;计算累积最大值或最小值:
- 计算累积的最大值或最小值,比如计算每个员工的累积最大销售额。
SELECT name, sales_date, sales_amount, MAX(sales_amount) OVER (PARTITION BY name ORDER BY sales_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_max FROM sales;
窗口函数的强大之处在于它们可以在不改变原始数据行的情况下,为每行添加额外的计算列,这使得它们在数据分析和报告中非常有用。