mysql 专业笔记 -- 第 8 章:使用变量

第 8.1 节:设置变量

  1. 你可以使用 SET 将变量设置为特定的字符串、数字或日期:
sql 复制代码
SET @var_string = 'my_var';
SET @var_num = '2';
SET @var_date = '2015-07-20';
  1. 你可以使用 := 将变量设置为 SELECT 语句的结果:
sql 复制代码
SELECT @var := '123';

(注意:当不使用 SET 语法赋值时,你需要使用 :=,因为其他语句(如 SELECT、UPDATE)中的 = 用于比较,所以当你添加冒号后跟等号时,表示"这不是比较,而是 SET"。)

  1. 你可以使用 INTO 将变量设置为 SELECT 语句的结果(这在需要动态选择要查询的分区时特别有用):
sql 复制代码
SET @start_date = '2015-07-20';
SET @end_date = '2016-01-31';

-- 获取用作分区名的年月值
SET @start_yearmonth = (SELECT EXTRACT(YEAR_MONTH FROM @start_date));
SET @end_yearmonth = (SELECT EXTRACT(YEAR_MONTH FROM @end_date));

-- 将分区放入变量
SELECT GROUP_CONCAT(partition_name)
FROM information_schema.partitions
WHERE table_name = 'partitioned_table'
  AND SUBSTRING_INDEX(partition_name, 'p', -1) BETWEEN @start_yearmonth AND @end_yearmonth
INTO @partitions;

-- 将查询放入变量。你需要这样做,因为 MySQL 在那个位置不能识别变量。你需要将变量的值与查询的其余部分拼接,然后作为预处理语句执行。
SET @query = CONCAT(
    'CREATE TABLE part_of_partitioned_table (PRIMARY KEY(id)) ',
    'SELECT partitioned_table.* ',
    'FROM partitioned_table PARTITION(', @partitions, ') ',
    'JOIN users u USING(user_id) ',
    'WHERE DATE(partitioned_table.date) BETWEEN ', @start_date, ' AND ', @end_date
);

-- 从 @query 准备语句
PREPARE stmt FROM @query;

-- 删除表(如果存在)
DROP TABLE IF EXISTS tech.part_of_partitioned_table;

-- 使用语句执行创建表
EXECUTE stmt;

第 8.2 节:在 SELECT 语句中使用变量实现行号和分组

假设我们有一个 team_person 表,如下所示:

图片占位符

sql 复制代码
CREATE TABLE team_person AS
SELECT 'A' team, 'John' person UNION ALL
SELECT 'B' team, 'Smith' person UNION ALL
SELECT 'A' team, 'Walter' person UNION ALL
SELECT 'A' team, 'Louis' person UNION ALL
SELECT 'C' team, 'Elizabeth' person UNION ALL
SELECT 'B' team, 'Wayne' person;

要为 team_person 表添加行号列,可以使用以下任一方法:

sql 复制代码
SELECT @row_no := @row_no + 1 AS row_number, team, person
FROM team_person, (SELECT @row_no := 0) t;

或者:

sql 复制代码
SET @row_no := 0;
SELECT @row_no := @row_no + 1 AS row_number, team, person
FROM team_person;

以上都会输出以下结果(示例):

复制代码
+------------+------+-----------+
| row_number | team | person    |
+------------+------+-----------+
| 1          | A    | John      |
| 2          | A    | Walter    |
| 3          | A    | Louis     |
| 4          | B    | Smith     |
| 5          | B    | Wayne     |
| 6          | C    | Elizabeth |
+------------+------+-----------+

最后,如果我们想要按 team 列分组生成行号:

sql 复制代码
SELECT
    @row_no := IF(@prev_val = t.team, @row_no + 1, 1) AS row_number,
    @prev_val := t.team AS team,
    t.person
FROM team_person t,
    (SELECT @row_no := 0) x,
    (SELECT @prev_val := '') y
ORDER BY t.team ASC, t.person DESC;

输出结果(示例):

复制代码
+------------+------+-----------+
| row_number | team | person    |
+------------+------+-----------+
| 1          | A    | Walter    |
| 2          | A    | Louis     |
| 3          | A    | John      |
| 1          | B    | Wayne     |
| 2          | B    | Smith     |
| 1          | C    | Elizabeth |
+------------+------+-----------+
相关推荐
ServBay2 分钟前
Claude Fable 5.5 测试曝光,但它在悄悄给你打分
后端·ai编程·claude
番茄啊28 分钟前
linux 开启xftp连接
linux·运维·服务器
IT规划师1 小时前
一文讲透五种发布机制:滚动、蓝绿、金丝雀、红黑与 AB
后端·面试
IT利刃出鞘1 小时前
Docker Compose--解决修改配置后不生效的问题
运维·docker·容器
java_logo1 小时前
Docker 部署 CloudBeaver:轻松搭建网页数据库管理平台
数据库·docker·容器·数据库管理·dbeaver·轩辕镜像·cloudbeaver
Lsetea1 小时前
Docker更新SSL证书后容器仍读旧文件:单文件挂载与目录挂载排查
运维·nginx·docker·https·ssl证书
Zhao-Jichao1 小时前
AI Prompting for Everyone 课程笔记 - P21 总结 Conclusion
人工智能·笔记
欢欢李2 小时前
【LTE L3 笔记 05】LTE同步信号
笔记·无线通信·物理层·lte·空口协议
Julien20042 小时前
管理机密(一)
运维·服务器·开发语言·学习方法
一条Go2 小时前
两套权限目录,三重闸门:Alioth 的多租户 RBAC 为什么这么拧
后端·程序员·github