[英]MYSQL - How to get row count for each day for the last 7 days and include days that don't exist in table
[英]How I can get last row of each day from big mysql table
我有超过 1000 万行的表。 我可以通过查询获得每天的第一行
select *
from history_average_crypto_stats
where `asset_id` = 1
and `created_at` >= DATE_SUB(NOW(), INTERVAL 1 YEAR)
group by date(`created_at`)
order by `created_at` asc
但我需要最后并尝试这个查询
select history_average_crypto_stats.*
from history_average_crypto_stats
join (
select MAX(`id`) id
from history_average_crypto_stats
where `asset_id` = 1
and `created_at` >= DATE_SUB(NOW(), INTERVAL 1 YEAR)
group by date(`created_at`)
) last ON history_average_crypto_stats.`id` = last.`id`
但它需要超过24秒......
我需要不到 1 秒。 表结构
CREATE TABLE `history_average_crypto_stats` (
`id` bigint(20) UNSIGNED NOT NULL,
`asset_id` bigint(20) UNSIGNED NOT NULL,
`price` double(20,6) NOT NULL,
`volume` bigint(20) NOT NULL,
`circulating_supply` bigint(20) NOT NULL,
`total_supply` bigint(20) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `history_average_crypto_stats`
ADD PRIMARY KEY (`id`),
ADD KEY `history_average_pairs_currency_id_asset_id_foreign` (`created_at`,`asset_id`) USING BTREE,
ADD KEY `asset_id` (`asset_id`);
ALTER TABLE `history_average_crypto_stats`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
一种选择使用相关子查询:
select h.*
from history_average_crypto_stats h
where h.created_at = (
select max(h1.created_at)
from history_average_crypto_stats h1
where h1.created_at >= date(h.created_at) and h1.created_at < date(h.created_at) + interval 1 day
)
这使用列created_at
来标识每天的最后一条记录。 目前尚不清楚您为什么使用id
代替(除非有重复的created_at
)。
为了性能,请考虑(created_at)
上的索引。
如果您也想对asset_id
进行asset_id
,就像在您的原始代码中一样,那么:
select h.*
from history_average_crypto_stats h
where h.asset_id = 1 and h.created_at = (
select max(h1.created_at)
from history_average_crypto_stats h1
where h1.asset_id = h.asset_id
and h1.created_at >= date(h.created_at)
and h1.created_at < date(h.created_at) + interval 1 day
)
然后在(asset_id, created_at)
上建立索引 - 我怀疑这比(created_at, asset_id)
上的原始索引更适合您的查询,因为created_at
上的范围条件。
如果你运行的是 MySQL 8.0,你也可以尝试窗口函数,看看性能是否更好:
select *
from (
select h.*, row_number() over(partition by date(created_at) order by created_at desc) rn
from history_average_crypto_stats
where asset_id = 1
) h
where rn = 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.