近期使用MySQL问题汇总

105 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

小问题多遇几次记住就可以了,这里记录一下做个备忘。

当前日期减一天

# 若对时间格式无要求,直接减即可 
select current_date()-1;
SELECT DATE_SUB(CURDATE(), INTERVAL 1 DAY);
# 若对时间格式有要求,格式化下 
select date_format(current_date()-1,'%Y-%m-%d');

# 扩展 获取减去一天1小时1分钟1秒
SELECT DATE_SUB('2025-01-01 00:00:00', INTERVAL '1 1:1:1' DAY_SECOND);

带索引的日期字段的查询

# sql1
SELECT * FROM subscription t WHERE DATE(t.active_time) = '2023-01-30';
# sql2
SELECT * FROM subscription t WHERE t.active_time LIKE '2023-01-30%';
# sql3
SELECT * FROM subscription t 
	WHERE t.active_time > '2023-01-30' AND t.active_time < '2023-02-11';

假设activiti_date的类型是datetime,且有索引,以上3条查询sql,是否使用索引。

由于函数调用,第1条查询不能使用索引。全部active_time必须即时转换为 DATE'2023-06-30' 比较。

第2个查询也不能使用索引。实际上是在进行字符串比较(因为 LIKE 运算符)。全部active_time值会即时转换为字符串。

只有最后一个可以使用索引。字符串 '2023-01-30''2023-02-11'被转换到DATETIME后与activiti_time做比较。

不要在MySQL中使用UTF-8

MySQL中的utf8实际上不是真正的UTF-8,MySQL中的utf8只支持每个字符最多3个字节而真正的UTF-8是每个字符最多4个字节。而MySQL中真正的UTF-8是utf8mb4 字符集。

查询更新时间最大的一条记录

SELECT
	a.id,
	a.other_table_id,
	a.updated_date 
FROM
	table1 a,
	(SELECT other_table_id, max( updated_date ) AS lastUpdate 
        FROM table2 GROUP BY other_table_id ) b 
WHERE
	a.other_table_id = b.other_table_id 
AND a.updated_date = b.last_update

生成随机ID

# 方案一:使用UUID
SELECT REPLACE(UUID(), '-', ''); 

# 方案二:使用毫秒时间戳
SELECT SUBSTR(date_format(NOW(3), '%Y%m%d%H%i%s%f'), 1, 17) as uniqueid

SUBSTR(str, pos, len) 函数的参数 pos 的坐标从 1 开始;
%Y 四位数字表示的年份;而 %y 两位数字表示的年份;
%m 两位数字表示的月份(01, 02, ..., 12);
%d 两位数字表示月中的天数(00, 01,..., 31);
%f 可以获得6位的微秒 microsecond;
年份4位,月份2位,天数2位,时分秒6位,毫秒保留3位,总位数为17位;

# 方案三:使用时间戳+随机数
SELECT CONCAT(date_format(NOW(), '%Y%m%d%H'), LPAD(FLOOR(RAND()*10000000),7,0)) as idNumber