使用大数据集Mysql在两组日期中查找最接近的较低日期
Posted
技术标签:
【中文标题】使用大数据集Mysql在两组日期中查找最接近的较低日期【英文标题】:Find closest lower date among two sets of dates with big data set Mysql 【发布时间】:2015-08-18 09:22:11 【问题描述】:我有两张桌子
“访问”基本上存储网站上的每次访问 |访问日期 |城市| ---------------------------------- | 2014-12-01 00:00:02 |巴黎 | | 2015-01-03 00:00:02 |马赛| “cityweather”每天存储 3 次很多城市的天气信息 |天气预报 |城市|温度 | ------------------------------------------ | 2014-12-01 09:00:02 |巴黎 | 20 | | 2014-12-01 09:00:02 |马赛| 22 |我确切地说,visit 表中可能有一些城市不在 cityweather 中,反之亦然,我只需要选取两个表共有的城市。
所以我的问题是:
我如何SELECT
为每个visitdate
低于访问日期的MAX(weatherdate)
?
应该是这样的:
|访问日期 |城市|早于 | -------------------------------------------------- ------ | 2014-12-01 00:00:02 |巴黎 | 2014-11-30 21:00:00 | | 2015-01-03 15:07:26 |马赛| 2015-01-03 09:00:00 |我试过这样的:
SELECT t.city, t.visitdate, d.weatherdate as beforedate
FROM visitsub as t
JOIN cityweatherfrsub as d
ON d.weatherdate =
( SELECT MAX(d.weatherdate)
FROM cityweatherfrsub
WHERE d.weatherdate <= t.visitdate AND d.city=t.city
)
AND d.city = t.city;
但是表格的大小使得不可能在“合理”的时间内(10^14 步)计算它:
|编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --- | 1 |初级 | d |全部 | idx_city,Idx_citydate |空 |空 |空 | 1204305 |使用位置 | | 1 |初级 |吨 |参考 | Idxcity, Idxcity日期 | idxcitydate | 303 | meteo.d.city | 111 |使用哪里;使用索引 | | 2 |依赖子查询 |城市天气|索引 |空 | idx_date | 6 |空 | 1204305 |使用哪里;使用索引 |我现在正在调查user-variable
的领域,比如@variable
,但我对它很陌生,只写了一些不起作用的东西Error Code: 1111. Invalid use of group function
:
SET @j :=0;
SET @k :=0;
SET @l :=0;
SET @m :=0;
CREATE TABLE intermedweather
SELECT @l as city, @k as visitdate, @j as beforedate
FROM visitsub t
JOIN cityweatherfrsub d
WHERE (@j := d.weatherdate) <= (@k := t.visitdate)
AND (@l := d.city) = (@m := t.city)
AND @j = MAX(d.weatherdate);
You can find here a similar post but it can't work for my problem
【问题讨论】:
在我看来,所有城市对两张表都是通用的。 你在哪里看到这个? 大声笑这是一个例子...... 嗯,它不是一个很有用的! 【参考方案1】:我不确定这是否是您需要的,但它应该可以解决问题。
SELECT t.visitdate, d.city, MAX(d.weatherdate) as beforedate
FROM cityweather d
JOIN visit t
ON d.weatherdate <= t.visitdate
AND d.city=t.city
GROUP BY t.visitdate, d.city;
【讨论】:
我现在正在尝试并让您更新。如果我只需要一个组('^^)...谢谢 您能接受我对EXPLAIN
的更新吗?您的查询运行了 3 个小时,我停止了它以打印我添加到您的答案中的内容。
cityweather
上有 INDEX(city, weatherdate)
吗?
请EXPLAIN
Marcin 的查询。
我想要,但他拒绝用EXPLAIN
编辑他的帖子它基本上说表d
它不使用索引并且需要读取54M 行,而Extra 是@ 987654328@ 对于表 t
它说它使用 3 行的索引 Idxcity,而 Extra 是 Using where
【参考方案2】:
试试这个:
SELECT t.visitdate, t.city, max(d.weatherdate) beforedate
FROM visit t inner JOIN cityweather d
on t.city=d.city
group by t.city,t.visitdate
【讨论】:
抱歉,我已经尝试过了,但是我的表(1M 行)和(6M 行)的大小使得无法计算... @YohanObadia 你有两个表中的城市索引吗? 正如我对@mxix 所说,我在两个表上都有 3 个索引:(城市)(日期)和(城市,日期)。问题是索引不能应用于分组函数,因此,在应用 Max 之后就像根本没有索引一样。 @YohanObadia 我更改了查询。你能在查询上运行explain
并发布结果吗?
这个和 Marcin 的一样,没有 d.weatherdate <= t.visitdate
条件。【参考方案3】:
替代方法,避免使用 MAX()
SELECT v.visitdate, v.city, w.weatherdate AS beforedate
FROM visit v
JOIN cityweather w
ON v.city = w.city
AND v.visitdate >= w.weatherdate
AND NOT EXISTS ( SELECT * FROM cityweather nx
WHERE nx.city = v.city
AND nx.weatherdate <= v.visitdate
AND nx.weatherdate > w.weatherdate
);
【讨论】:
有趣,也许它可以帮助我以我想要的方式使用我的索引,我试图避免子查询以提高性能,但我会在其他建议完成运行时尝试它。谢谢 在正常的 DBMSses 上,考虑到相关索引,避免使用 max() 通常会产生更好的性能。 (max() 通常需要给定范围内的所有行)【参考方案4】:可能是这样的:
select
V.*,
(
select
MAX(weatherdate)
from Weather W
where
W.weatherdate < V.visitdate and
W.city = V.city
) beforedate
from Visit V
where
exists ( select 1 from Weather where V.city = W.city)
【讨论】:
与 Ormoz 的评论相同 确保您已为此类查找正确索引表 我在两个表上都有 3 个索引:(城市)(日期)和(城市,日期)。问题是索引不能应用于分组函数,因此,在应用 Max 之后就像根本没有索引一样。W.city = W.city
应该说W.city = V.city
【参考方案5】:
我最终自己找到了答案。这一切都归结为缩小表城市天气的选择范围。因此,我分两步完成,以避免到目前为止我们遇到的 O(n^2) 问题,并且我减小了在其他答案中找到的第一个表(有时是虚拟表)的大小:
第一步(关键的一步):
CREATE TABLE intermedtable
SELECT t.city, t.visitdate, d.weatherdate
FROM visit as t
JOIN cityweather as d
WHERE d.city=t.city AND d.weatherdate <= t.visitdate AND d.weatherdate + interval 1 day >= t.visitdate;
与我们之前的情况相比,这里至关重要的是d.weatherdate + interval 1 day >= t.visitdate
条件。它“只”花了 22 分钟。
第二步是为每一对(city, visitdate)
找到MAX(weatherdate)
:
Create table beforedatetable
SELECT city, visitdate, max(weatherdate) as beforedate
FROM intermedtable
GROUP BY city, visitdate;
使用这个解决方案,我从 16 小时的计算(最后会崩溃)缩短到 32 分钟。
这个答案的核心是通过添加d.weatherdate + interval 1 day >= t.visitdate
条件来减小上一个答案中创建的虚拟表的大小。这是基于这样一个事实,即感兴趣的天气日期与访问日期的距离不能超过一天。
【讨论】:
以上是关于使用大数据集Mysql在两组日期中查找最接近的较低日期的主要内容,如果未能解决你的问题,请参考以下文章