【发布时间】:2020-07-24 21:50:45
【问题描述】:
我在这里设置了一个小提琴:https://www.db-fiddle.com/f/snDGExYZgoYASvWkDGHKDC/2
还有:
架构:
CREATE TABLE `scores` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`shift_id` int unsigned NOT NULL,
`employee_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`score` double(8,2) unsigned NOT NULL,
`created_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO scores(shift_id, employee_name, score, created_at) VALUES
(1, "John", 6.72, "2020-04-01 00:00:00"),
(1, "Bob", 15.71, "2020-04-01 00:00:00"),
(1, "Bob", 54.02, "2020-04-01 08:00:00"),
(1, "John", 23.55, "2020-04-01 13:00:00"),
(2, "John", 9.13, "2020-04-02 00:00:00"),
(2, "Bob", 44.76, "2020-04-02 00:00:00"),
(2, "Bob", 33.40, "2020-04-02 08:00:00"),
(2, "James", 20, "2020-04-02 00:00:00"),
(3, "John", 20, "2020-04-02 00:00:00"),
(3, "Bob", 20, "2020-04-02 00:00:00"),
(3, "Bob", 30, "2020-04-02 08:00:00"),
(3, "James", 10, "2020-04-02 00:00:00")
查询 1:
-- This doesn't work
SELECT
employee_name,
DATE_FORMAT(created_at, '%Y-%m-%d') AS `date`,
ANY_VALUE(AVG(score) OVER(PARTITION BY(ANY_VALUE(created_at)))) AS `average_score`
FROM
scores
GROUP BY
employee_name, date;
查询 2:
SELECT
employee_name,
DATE_FORMAT(created_at, '%Y-%m-%d') AS `date`,
ANY_VALUE(AVG(score)) AS `average_score`
FROM
scores
GROUP BY
employee_name, date;
查询 3:
-- This works but scales very poorly with millions of rows
SELECT
t1.employee_name,
ANY_VALUE(DATE_FORMAT(t1.created_at, '%Y-%m-%d')) AS `date`,
ANY_VALUE(SUM(t1.score) / (
SELECT SUM(t2.score)
FROM scores t2
WHERE date(t2.created_at) = date(t1.created_at)
) * 100) AS `average_score`
FROM
scores t1
GROUP BY
t1.employee_name, date;
第三个查询正确执行,但在我的测试中,当扩展到数百万行时,速度非常慢。我认为这是因为它是一个相关的子查询并且运行了数百万次。
前两次尝试是我尝试创建使用 MySQL 8 窗口函数来分区平均计算。然而,这些都产生了意想不到的结果。给定日期的average_scores 总数应为 100,就像在第三个查询中一样。
有谁知道更有效的计算方法吗?
还值得注意的是,实际上,查询中还会有一个WHERE IN,以按特定的shift_ids 进行过滤。给出的shift_ids 的数量可能有数十万,最高可达一百万。
正在考虑的另一件事是 ElasticSearch。是否有助于以更快的方式计算这些?
【问题讨论】:
-
请向我们展示您期望的结果。
-
@GMB 查询三给出了正确的结果,并显示在小提琴中。但它根本不能很好地扩展。
标签: mysql aggregate-functions window-functions mysql-8.0