同样是 MySQL 8,这个我问题我硬是没搞明白会这样,希望大家帮我分析一下

2022-03-25 14:31:10 +08:00
 CyJaySong

有一个表

CREATE TABLE `trade_account_total_daily_record`
(
    `date`         date           NOT NULL COMMENT '日期',
    `account_type` int            NOT NULL COMMENT '账户类型',
    `balance`      decimal(20, 2) NOT NULL DEFAULT 0.00 COMMENT '账户余额',
    `created_at`   datetime       NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at`   datetime       NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (`date`, `account_type`)
) ;

我执行

SELECT DATE_FORMAT(CURRENT_TIMESTAMP, '%Y-%m-%d'), 1, IFNULL(SUM(balance),0) + 10
FROM trade_account_total_daily_record WHERE account_type = 1 ORDER BY date DESC LIMIT 1 

能正确给出结果, 但是执行

INSERT INTO trade_account_total_daily_record (`date`, `account_type`, `balance`)
SELECT DATE_FORMAT(CURRENT_TIMESTAMP, '%Y-%m-%d'), 1, IFNULL(SUM(balance),0) + 10
FROM trade_account_total_daily_record WHERE account_type = 4 ORDER BY date DESC LIMIT 1
ON DUPLICATE KEY UPDATE `balance`=VALUES(`balance`) 

就报 Column 'date' cannot be null ,奇怪的是阿里云 RDS 数据库(mysql-8.0.25)会这样,我本地的 8.0.28 没问题

3155 次点击
所在节点    MySQL
34 条回复
encro
2022-03-25 17:56:20 +08:00
@CyJaySong

明白了,你是想不存在查前一天的,再累加。
encro
2022-03-25 17:57:30 +08:00
我是想每天都只加当天的,没必要去加前一天的。
encro
2022-03-25 18:07:43 +08:00
@CyJaySong

ORDER BY date DESC LIMIT 1 ,一条语句主键,谈什么性能?
CyJaySong
2022-03-25 18:07:44 +08:00
@encro #回复 21,22 是的,这样可以生成各账户类型的每日总结余额
CyJaySong
2022-03-25 18:09:30 +08:00
@encro 回复#23 期初我也这样么认为的,但是即便是 LIMIT 1 情况下,SUM 函数会导致全表扫描,就很皮
encro
2022-03-25 18:09:36 +08:00
where account_type = 4 ORDER BY date DESC LIMIT 1

索引顺序导致用不了主键索引。。。
CyJaySong
2022-03-25 18:11:32 +08:00
@encro 回复#26, 用#6 就很快哦
encro
2022-03-25 18:20:30 +08:00
@CyJaySong

你删掉当天存在的值再试试,说不定没跑查询或者命中 cache 呢。

INSERT INTO trade_account_total_daily_record (`date`, `account_type`, `balance`)
SELECT DATE_FORMAT(CURRENT_TIMESTAMP, '%Y-%m-%d'), 4, IFNULL(SUM(tmp.balance),0) + 10,FROM (SELECT balance FROM trade_account_total_daily_record WHERE account_type = 4 ORDER BY `date` DESC LIMIT 1) AS tmp
ON DUPLICATE KEY UPDATE `balance`=VALUES(`balance`)


我还没琢磨透 SUM(tmp.balance) 和 WHERE account_type = 4 ORDER BY `date` DESC LIMIT 1 的用意。。。。
encro
2022-03-25 18:21:52 +08:00
LIMIT 1 不是只有一行结果吗?还需要 sum?
encro
2022-03-25 18:34:41 +08:00
INSERT INTO trade_account_total_daily_record (`date`, `account_type`, `balance`)
SELECT CURRENT_DATE , 4, IFNULL((SELECT balance FROM trade_account_total_daily_record WHERE account_type = 4 ORDER BY `date` DESC LIMIT 1),0) + 10
ON DUPLICATE KEY UPDATE `balance`=`balance`

?
CyJaySong
2022-03-25 18:38:40 +08:00
@encro 回复 #29 如果执行的时候数据库没有 account_type = 4 的数据呢,你看看结果会怎样
encro
2022-03-25 18:40:10 +08:00
@CyJaySong

不知道,前面也加了 isnull 。
encro
2022-03-25 18:40:40 +08:00
就是看同表更新好像是需要建立临时表。不知道 8.0 了。
CyJaySong
2022-03-25 18:43:13 +08:00
@encro 回复#32 在没有复合 account_type = 4 的数据的情况下,光有 isnull 没用

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/842853

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX