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 |
+------------+------+-----------+
相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
一隅论数智4 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
XiHongShi20164 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
虎头金猫4 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码4 天前
别再前后端各写一套表单校验了
java·后端
爱吃苹果的日记本4 天前
离散数学第六课
学习·离散数学
小白男神4 天前
MySQL进阶学习四(存储过程、游标、触发器)
mysql