MySQL查询难题 - 找到最近的日期

时间:2010-05-14 20:35:59

标签: mysql join max datediff min

我看了一遍,还没有找到一种聪明的方法来解决这个问题,尽管我确信有一种可能:

一张历史数据表包含季度信息:

CREATE TABLE Quarterly (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
PRIMARY KEY (unique_ID));

另一个历史数据表(非常大)包含每日信息:

CREATE TABLE Daily (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
qtr_ID INT UNSIGNED,
PRIMARY KEY (unique_ID));

qtr_ID字段不是填充数据库的每日数据源的一部分 - 相反,我需要使用Quarterly.unique_ID行ID追溯填充Daily表中的qtr_ID字段,使用最新的关于该数据源的Daily.date_posted的季度数据。

例如,如果季度数据是

  

101 2009-03-31 1 4.5
   102 2009-06-30 1 4.4
   103 2009-03-31 2 7.6
   104 2009-06-30 2 7.7
   105 2009-09-30 1 4.7

,每日数据

  

1001 2009-07-14 1 3.5 ??
  1002 2009-07-15 1 3.4&&
  1003 2009-07-14 2 2.3 ^^

那么我们会想要?? qtr_ID字段将被指定为“102”,作为该日期该数据源的最新季度,以及&&也将是'102',^^将是'104'。

挑战包括两个表(特别是每日表)实际上非常大,它们无法规范化以消除重复日期或以其他方式优化,并且对于某些日常条目,没有前一季度条目。< / p>

我尝试过各种各样的连接,使用datediff(挑战是找到大于零的最小值),以及其他尝试,但没有什么对我有用 - 通常我的语法在某个地方破坏。欢迎任何想法 - 我将执行任何基本想法或概念并报告。

3 个答案:

答案 0 :(得分:1)

使用类似以下内容的季度id的子查询:

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)

当然,这可能不会为您提供最佳性能,并且它假定日期按顺序添加到季度(否则为order by date_posted)。但是,它应该可以解决您的问题。

您可以在INSERTUPDATE语句中使用此子查询作为qtr_ID表的Daily字段的值。

答案 1 :(得分:0)

以下似乎完全符合预期,但肯定是丑陋的(对同一个DATEDIFF进行了三次调用!!),也许是通过查看有人可能能够进一步减少或改进它的工作查询:

UPDATE Daily SET qtr_ID = (select unique_ID from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) = 
(SELECT MIN(DATEDIFF(Daily.date_posted, Quarterly.date_posted)) from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) > 0));

答案 2 :(得分:0)

在对此查询进行更多工作之后,我最终在原始概念上获得了巨大的性能提升。最重要的改进是在Daily和Quarterly表中创建索引 - 在Daily I中创建索引(datasource,date_posted)和(date_posted,datasource)USING BTREE和on(datasource)USING HASH,在Quarterly中我做了同样的事情。这有点矫枉过正,但它确保我有一个查询引擎可以使用的选项。这将查询时间缩短到不到原来的1%。 (!!)

然后,我了解到,根据我的特殊情况,我可以使用MAX()而不是ORDER BY和LIMIT,因此我使用MAX()调用来获取相应的unique_ID。这使查询时间减少了大约20%。

最后,我了解到使用InnoDB存储引擎,我可以使用任何一个查询来分割我正在更新的Daily表的块,这允许我使用一点点肘部和脚本来多线程化查询。并行处理运行良好,每个线程都线性地减少了查询时间。

因此,基本查询的表现比我自己的第一次尝试要好1000倍:

UPDATE Daily
SET qtr_ID =
(
  SELECT MAX(unique_ID)
  FROM Quarterly
  WHERE Daily.datasource = Quarterly.datasource AND
        Daily.date_posted > Quarterly.dateposted
)
WHERE unique_ID > ScriptVarLowerBound AND
      unique_ID <= ScriptVarHigherBound
;