mysql - mysql sub select很慢
问题描述
我有一张这样的桌子:
-------------------------------
| id | valid_until | username|
-------------------------------
| 1 | 2020-01-01 | user1 |
-------------------------------
| 1 | 2020-01-01 | user2 |
-------------------------------
| 1 | 2020-01-02 | user3 |
-------------------------------
| 1 | 2020-01-02 | user4 |
-------------------------------
| 1 | 2020-01-03 | user5 |
-------------------------------
| 1 | 2020-01-03 | user6 |
-------------------------------
| 1 | 2020-01-03 | user7 |
-------------------------------
这是用户订阅表,valid_until
表示订阅何时结束。
我想知道每天的活跃订阅,所以我有一个范围,例如2020-01-01
TO 2020-01-03
,这是我的查询:
SELECT
valid_until qva,
(SELECT
COUNT(iod.id) AS ct
FROM
`order_detail` iod
WHERE
valid_until > qva)
FROM
`order_detail`
WHERE
valid_until >= '2020-01-01'
AND valid_until <= '2020-01-03'
GROUP BY qva
但是这个查询太慢了,我的查询有什么问题?响应时间(230 秒)
解决方案
根据 SQL 标准,您的查询无效。您有GROUP BY qva
(并且通常不允许在此处使用别名,但在 MySQL 和 MariaDB 中是这样),但您没有对子查询结果应用聚合函数。MySQL 以违反标准而闻名,它们默默地应用于ANY_VALUE
此类未聚合的表达式。
这会使查询变慢。对于日期范围内的每个订单,都会评估计数,仅在最后每个日期选择其中一个计数。
所以,让我们从头开始构建查询。您希望给定日期范围内的每一天都有一个结果行。那是:
select distinct valid_until
where valid_until between date '2020-01-01' and date '2020-01-03'
from order_detail;
然后,对于这些日期中的每一个,您都想获得计数。您可以像在原始查询中一样在子查询中执行此操作。我想它必须>=
不是>
,因为订单在一天之前有效,当天仍然有效(或者至少这是我所期望的)。
SELECT
dates.day,
(
select count(*)
from order_detail od
where od.valid_until >= dates.day
) as ct
FROM
(
select distinct valid_until as day
where valid_until between date '2020-01-01' and date '2020-01-03'
from order_detail
) dates
order by dates.day;
(这假设这valid_until
只是一个日期。如果它是一个日期时间,你将不得不稍微调整这个查询。)
更新:
正如 ysth 在请求评论中告诉您的那样,您的查询只会让您获得在给定范围内存valid_until
在于您的表中的天数。我的也是。如果您无论如何都想要三天,则必须替换子查询并使其独立于表,例如
FROM
(
select date '2020-01-01' as day union all
select date '2020-01-02' as day union all
select date '2020-01-03' as day
) dates
推荐阅读
- android - Android UI Automate - 在硬件设备上运行测试而不使用 ADB shell
- python-3.x - 我正在尝试根据他们给定的指令运行“GrouPy”的代码,但它给了我错误。我正在使用 Python 3、Cuda 9 和 gcc6
- javascript - 轮播未正确加载
- c# - 从 URI 查询字符串解析字符串总是返回空值
- excel - 平均公式错误
- python - Django 的最后一个对象的最小查询集,其中恰好 n 条记录满足条件
- spring-boot - 在 Spring Boot 应用程序中配置安全性
- react-native - Chrome调试中GET url末尾的问号
- javascript - 动态更改反应模式数据
- android - 更改数据后如何刷新chartView