2

这似乎应该是一个非常基本的问题,并且周围有很多类似的问题,但是经过数小时的研究和反复试验,我找不到答案。如果这是重复的,我很抱歉。

我想加入一个基于两个条件的表:

column_1 = something_1 AND column_2 = max(所有可能的条目小于 something_2)。

我想我应该能够做到这一点:

Select t1.id, t2.id from table1 as t1
join
(select t1.id, max(t2.condition_2) as big_condition_2 from table1 as t1
join table2 as t2
on t2.condition_1 = t1.condition_1 and t2.condition_2 < t1.condition_2
group by t1.id) as t3
on t3.id = t1.id
join table2 t2
on t2.condition_1 = t1.condition_1 and t2.condition_2 = t3.big_condition_2

此查询当前在 20 分钟后超时,我不知道删除超时需要多长时间。我很确定我做错了什么。

每个表平均有大约 100 种类型,condition_1然后每个条件有大约 4000 个不同的condition_2值。所以每个表有 300k - 500k 行。然后我估计子查询应该生成大约 2000 x 100 = 200k 连接 - 浪费,但我认为这不会导致如此长的延迟。请注意,condition_1是一个int并且condition_2是一个varchar(21)

我在每个引用字段上都有索引,可以是单独的,也可以是多个必要的,但是我生成这个 t3 表的事实可能会大大减慢速度,因为与 t3 的连接不使用索引?

不过,我认为更根本的是,我想知道是否有一种方法可以选择要加入的特定值,而无需进行所有这些否则不必要的联接?也就是说,执行类似(伪代码)的操作:

select t1.id, t2.id from table1 as t1
join table2 as t2
on t2.condition_1 = t1.condition_1
and t2.condition_2 = max(t2.condition_2 where t2.condition_2 > t1.condition_1)

在此先感谢您的帮助!

更新

应史蒂夫的要求,我尝试对查询进行解释,但在 20 分钟后它也超时了。然后我尝试仅对子查询部分进行解释并得到以下输出

更新 2我添加了一些新索引并在子查询上重新运行解释。以下是结果(已格式化,因此它们现在也更具可读性):

id  select_type  table  type    possible_keys                           key                  key_len  ref                       rows    Extra
1   SIMPLE       esnap  index   ticker_id,ticker_id_2,date_time_GMT     PRIMARY              4        null                      20  
1   SIMPLE       ep     ref     primary_ticker_id,secondary_ticker_id   secondary_ticker_id  5        adr.esnap.ticker_id       1       Using where
1   SIMPLE       ets    ref     ticker_id,date_time_GMT                 ticker_id            5        adr.ep.primary_ticker_id  22430   Using where; Using index

作为解释的方式,esnapis tableAetsistableBep是一个表,它是将 tableA 连接到 tableB 所需的中间表。所以子查询实际上是:

select esnap.security_snap_id, max(ets.date_time_GMT) as snap_time from
equity_snapshots esnap
join equity_pairs ep on ep.secondary_ticker_id = esnap.ticker_id
join equity_trade_snaps ets on ets.ticker_id = ep.primary_ticker_id and
ets.date_time_GMT < esnap.date_time_GMT
group by esnap.security_snap_id

其中ticker_id是一个intdate_time_GMT是一个varchar(21)

问不可能?

进一步考虑,我认为子查询会生成一个太大的表。大约有 100 对要匹配 ( condition_1),每对在 tableA 中有大约 6500 个不同的 id,在 tableB 中有 3500 个不同的 id。这意味着在分组之前将有大约 100 * 6500 * (3500/2) = 11 亿行加入。

诉诸Java...

除非其他人可以建议一种避免子查询的方法(即只加入“最大小于”,而不是“全部小于,然后分组”)我想我会放弃并使用 java 来导入整个表,做它的事情,然后将结果输出回mySql。对于应该更简单的事情来说,这一切似乎都非常耗时......所以如果有人有更好的解决方案,请告诉我。

4

1 回答 1

0
SELECT t3.id, t2.id from (select t1.id,t1.condition_1, max(t2.condition_2) as big_condition_2 from table1 as t1
JOIN table2 as t2
on t2.condition_1 = t1.condition_1 and t2.condition_2 < t2.condition_2
group by t1.id,t1.condition_1 ) as t3

JOIN table2 t2
on t2.condition_1 = t3.condition_1 and t2.condition_2 = t3.big_condition_2

需要更改条件t2.condition_2 < t2.condition_2,因为总是错误的可能是错字。

于 2013-03-08T10:01:34.650 回答