这似乎应该是一个非常基本的问题,并且周围有很多类似的问题,但是经过数小时的研究和反复试验,我找不到答案。如果这是重复的,我很抱歉。
我想加入一个基于两个条件的表:
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
作为解释的方式,esnap
is tableA
、ets
istableB
和ep
是一个表,它是将 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
是一个int
,date_time_GMT
是一个varchar(21)
。
问不可能?
进一步考虑,我认为子查询会生成一个太大的表。大约有 100 对要匹配 ( condition_1
),每对在 tableA 中有大约 6500 个不同的 id,在 tableB 中有 3500 个不同的 id。这意味着在分组之前将有大约 100 * 6500 * (3500/2) = 11 亿行加入。
诉诸Java...
除非其他人可以建议一种避免子查询的方法(即只加入“最大小于”,而不是“全部小于,然后分组”)我想我会放弃并使用 java 来导入整个表,做它的事情,然后将结果输出回mySql。对于应该更简单的事情来说,这一切似乎都非常耗时......所以如果有人有更好的解决方案,请告诉我。