【MySQL】# 自定义变量、一行数据与多行的转换、IF函数

1. 自定义变量

和Java 一样,MySQL也允许用户自定义变量进行使用。它是一个用来存储内容的临时容器,在连接 MySQL的整个过程中都存在。

定义方式

  • 简单变量SET @num := 1
  • 查询赋值SET @min_num := (SELECT MIN(number) FROM student)
  • 日期SET @last_day := CURRENT_DATE -INTERVAL 1 DAY

简单使用

  • SELECT * FROM student WHERE number > @num

注意

  • 不能在使用常量或者标识符的地方使用自定义变量(例如表名、列名等)
  • 不能用自定义变量来做连接间的通信
  • 赋值符号 := 的优先级非常低
  • 使用未定义的变量不会产生任何语法错误

案例一

可以在给一个变量赋值的同时使用这个变量,即“左值”特性

SET @rowNum := 0;

SELECT stuId, @rowNum := @rowNum + 1 FROM student

案例二避免重复查询刚更新的数据

用户希望更新一条数据后,立马获取到该条数据的更新时间

-- 之前的做法
UPDATE student SET updateTime = NOW() WHERE stud_id = 1;
SELECT updateTime FROM student WHERE stud_id = 1;

-- 使用变量后
UPDATE student SET updateTime = NOW() WHERE stud_id = 1 AND @now := NOW();
SELECT @now;

使用变量虽然也是需要两个SQL,但是第2个查询无需访问数据表,加快了检索时间

案例三取值的顺序

让变量的赋值和取值发生在执行查询的同一阶段,不然可能会出现赋值后还没更新,取到原来值的问题

SET @rownum := 0;

SELECT user_name, @rownum row_num
FROM student
WHERE (@rownum := @rownum + 1) <= 1

案例四偷懒的 UNION

假设需要查找某条数据,先在一个频繁访问的表查找热数据,找不到再去另外一个较少访问的表查找冷数据

  • 如果直接使用 UNION ALL,那无论第一个表有没有查到数据,都会去第二个表中再找一次

    SELECT id FROM student WHERE id = 123
    UNION ALL
    SELECT id FROM student_archived WHERE id = 123;
    

使用变量则可以规避这个问题:

SELECT GREATEST( @found := - 1, id ) AS id FROM	student WHERE id = 123 -- 先查找热数据
UNION ALL
SELECT id FROM student_archived WHERE id = 123 AND @found IS NULL  -- 如果查不到就去查找冷数据
UNION ALL
SELECT 1 FROM DUAL WHERE ( @found := NULL ) IS NOT NULL;  -- 都查不到的情况

2. 一行与多行之间的转换

image-20220707220719707

2.1 一行转多行

解决:借助 mysql 库的 help_topic 表

SELECT
	d.id,
	SUBSTRING_INDEX( SUBSTRING_INDEX( d.class_name, ',', ht.help_topic_id + 1 ), ',', - 1 ) splitId 
FROM
	demo d
	JOIN mysql.help_topic ht ON ht.help_topic_id < ( LENGTH( d.class_name ) - LENGTH( REPLACE ( d.class_name, ',', '' )) + 1 ) 
WHERE
	d.id = 4

2.2 多行转一行

合并行使用 GROUP_CONCAT 函数,如果出现编码问题导致查询出来的是 blob 数据类型时,使用 CONVERT(GROUP_CONCAT(需要转换的字段名) USING utf8) 解决

SELECT
	class_name,
	GROUP_CONCAT( id SEPARATOR ';' ) groupId -- SEPARATOR 指定什么字符作为分隔符
FROM
	demo 
GROUP BY
	class_name

3. IF函数

IF 函数,通过判断条件来返回特定值

IF(expr, result_true, result_false) -- 如果表达式 expr的结果为真,则返回 result_true,否则返回 result_false

案例:在 student 表中,男生用 1表示,女生用 0 表示,查询student 表,并用汉字展示性别

SELECT
	stu_name,
	IF( sex = 1, '男', '女' ) sex 
FROM
	student

tudent 表中,男生用 1表示,女生用 0 表示,查询student 表,并用汉字展示性别

SELECT
	stu_name,
	IF( sex = 1, '男', '女' ) sex 
FROM
	student
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在 MySQL 中,可以使用 CONCAT 函数来将多行数据合并为一行。例如: ``` SELECT CONCAT(col1, ' ', col2, ' ', col3) FROM table_name; ``` 上面的 SQL 语句将会在 col1、col2 和 col3 之间插入空格,并将这三列合并为一行。 如果你想将一行数据分解为多行,你可以使用 SUBSTRING_INDEX 函数。例如: ``` SELECT SUBSTRING_INDEX(col, ' ', 1) AS col1, SUBSTRING_INDEX(SUBSTRING_INDEX(col, ' ', 2), ' ', -1) AS col2, SUBSTRING_INDEX(col, ' ', -1) AS col3 FROM table_name; ``` 上面的 SQL 语句假设 col 列是由多个单词组成的字符串,并且用空格分隔。它会将 col 列分解为三个列:col1、col2 和 col3,分别包含 col 列的第一个、第二个和最后一个单词。 注意:以上语句假设你已经知道了分解后的列的数量,以及每列的单词数量。如果你不知道这些信息,可能需要使用其他方法来分解字符串。 ### 回答2: 如果要将一行数据分解成多行数据,可以使用MySQL中的一些内置函数和操作符来实现。 首先,使用内置函数`SUBSTRING_INDEX`来分解行数据。该函数将字符串根据指定的分隔符拆分成多个子字符串,并返回指定位置的子字符串。 然后,可以使用内置函数`UNION ALL`将多个子字符串合并成多行数据。`UNION ALL`操作符可以将多个查询结果合并成一个结果集,而不进行任何去重操作。 具体步骤如下: 1. 使用`SELECT`语句查询需要分解的行数据,例如:`SELECT column_name FROM table_name WHERE condition;` 2. 使用`SUBSTRING_INDEX`函数将行数据拆分成多个子字符串,例如:`SELECT SUBSTRING_INDEX(column_name, ',', 1) AS new_column FROM table_name WHERE condition;` 这里的`','`是分隔符,`1`表示获取第一个子字符串,`new_column`是新的列名。 3. 使用`UNION ALL`操作符将多个子字符串合并成多行数据,例如:`SELECT SUBSTRING_INDEX(column_name, ',', 1) AS new_column FROM table_name WHERE condition UNION ALL SELECT SUBSTRING_INDEX(column_name, ',', 2) AS new_column FROM table_name WHERE condition UNION ALL SELECT SUBSTRING_INDEX(column_name, ',', 3) AS new_column FROM table_name WHERE condition;` 这里的`','`是分隔符,`2`表示获取前两个子字符串,`3`表示获取前三个子字符串。 通过以上步骤,可以将一行数据分解成多行数据。根据实际情况,可以调整分隔符和截取的子字符串个数来适应不同的需求。 ### 回答3: 在MySQL中,一行数据可以通过多种方法进行分解为多行数据。以下是一些常见的方法: 1. 使用UNION ALL:可以使用UNION ALL操作符将一行数据拆分为多行数据。例如,假设有一张表orders,包含字段order_id、customer_id和order_items。可以使用以下查询语句将每个订单项拆分为单独的行: SELECT order_id, customer_id, order_item FROM orders UNION ALL SELECT order_id, customer_id, order_item2 FROM orders UNION ALL SELECT order_id, customer_id, order_item3 FROM orders 这样可以将一行数据拆分为多行数据,每行数据都包含相同的order_id和customer_id,但不同的order_item。 2. 使用连接查询:可以使用连接查询来将一行数据分解为多行数据。假设有两张表orders和order_items,可以使用以下查询语句来实现: SELECT orders.order_id, orders.customer_id, order_items.order_item FROM orders JOIN order_items ON orders.order_id = order_items.order_id 这样可以将orders表中的每一行数据与order_items表中的多行数据连接起来,将一行数据分解为多行数据。 3. 使用子查询:可以使用子查询的方式将一行数据分解为多行数据。例如,假设有一张表orders,包含字段order_id和order_items,可以使用以下查询语句来实现: SELECT order_id, customer_id, (SELECT order_item FROM order_items WHERE order_id = orders.order_id) AS order_item FROM orders 这样可以通过子查询构造一个查询,将每个order_id拆分为多行数据,每行数据都包含相同的order_id和customer_id。 这些方法可以根据具体的需求和数据结构选择适合的方式将一行数据分解为多行数据

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LRcoding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值