加入“最大值小于......”,而不必首先加入到不到的东西

时间:2013-03-08 09:06:19

标签: mysql

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

我想根据两个条件加入一个表:

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_1intcondition_2varchar(21)

我在每个引用的字段上都有索引,无论是单独的还是多个必要的,但是我生成这个t3表的事实可能会大大降低速度,因为t3的连接不使用索引? / p>

我认为从根本上说,我想知道的是,如果有一种方法可以选择加入的特定值而不进行所有这些不必要的连接?也就是说,做一些像(伪代码):

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

作为解释,esnaptableAetstableBep为表格,是加入所需的中间表格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_idintdate_time_GMTvarchar(21)

问不可能?

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

诉诸Java ...

除非别人能提出一种避免子查询的方法(即只加入“max less than”,而不是“ALL all than,then group”)我想我会放弃并使用java来导入整个表,做它的事情,然后将结果输出回mySql。对于应该更简单的事情来说,这一切似乎非常耗时......所以,如果有人有更好的解决方案,请告诉我。

1 个答案:

答案 0 :(得分: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因为总是错误可能是拼写错误。