使用大数据集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 &lt;= 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 &gt;= 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 &gt;= t.visitdate 条件来减小上一个答案中创建的虚拟表的大小。这是基于这样一个事实,即感兴趣的天气日期与访问日期的距离不能超过一天。

【讨论】:

以上是关于使用大数据集Mysql在两组日期中查找最接近的较低日期的主要内容,如果未能解决你的问题,请参考以下文章

在最接近指定日期的列表中查找上一个日期

根据最接近的日期时间合并两个数据框

如何用python在两组数据中找相应匹配的数据?

R - 在两组列中搜索两个条件

MySQL查找先前值较低的峰值? [关闭]

如何在GEO数据库中比较两个子集 我想在两组芯片数据之间比较存在表达差异4倍以上的基因 应该怎么操作