第 8.1 节:设置变量
- 你可以使用
SET将变量设置为特定的字符串、数字或日期:
sql
SET @var_string = 'my_var';
SET @var_num = '2';
SET @var_date = '2015-07-20';
- 你可以使用
:=将变量设置为 SELECT 语句的结果:
sql
SELECT @var := '123';
(注意:当不使用 SET 语法赋值时,你需要使用 :=,因为其他语句(如 SELECT、UPDATE)中的 = 用于比较,所以当你添加冒号后跟等号时,表示"这不是比较,而是 SET"。)
- 你可以使用
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 |
+------------+------+-----------+