2

我已经查看了所有内容,但还没有找到一种智能的方法来处理这个问题,尽管我确信一个是可能的:

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

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”。

挑战包括这两个表(尤其是每日表)实际上都非常大,它们不能被规范化以摆脱重复的日期或以其他方式优化,并且对于某些每日条目没有之前的季度条目。

我尝试了各种连接,使用 datediff (挑战是找到大于零的 datediff 的最小值)和其他尝试,但没有任何东西对我有用 - 通常我的语法在某个地方出现问题。欢迎任何想法 - 我将执行任何基本想法或概念并报告。

4

3 回答 3

1

只需使用以下方式子查询季度 ID:

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

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

您将在您的INSERTorUPDATE语句中使用此子查询作为表的qtr_ID字段值Daily

于 2010-05-14T20:42:54.147 回答
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));
于 2010-05-17T21:01:26.080 回答
0

在对这个查询进行了更多工作之后,我最终获得了对原始概念的巨大性能改进。最重要的改进是在 Daily 和 Quarterly 表中创建索引 - 在 Daily 中,我在 (datasource, date_posted) 和 (date_posted, datasource) USING BTREE 和 (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
;
于 2010-05-31T21:29:25.170 回答