Question

Hi i have a simple table of live course data

t_course_live -->
id (INT) (PRIMARY KEY AUTO_INCREMENT)
trade_timestamp DATETIME
rate FLOAT

id | trade_timestamp     | rate
1  | 2014-04-28 20:53:32 | 1.38629
2  | 2014-04-28 20:53:34 | 1.38623
3  | 2014-04-28 20:53:39 | 1.38625

So I make sure that there is hole in the auto_increment sequence and the trade_timestamps do always increment with the ids => trade_timestamp(id) < trade_timestamp(id+1)

I want to join each row with the "next parent". That means the row with the id+1 so i can calculate the difference between the timestamps. My SQL approach looks like the following, which does the job, but takes way too long, cause there are already 900k+ entries.

SELECT ... (do the calculation with t1.trade_timesamp and t2.trade_timestamp) ...
FROM t_course_live t1
LEFT JOIN (
  SELECT t2_inner.*, (t2_inner.id+1) AS next_row 
  FROM t_course_live t2_inner
  WHERE DATE(t2_inner.trade_timestamp) = '2014-04-28'
) AS t2 ON t1.id = t2.next_row
WHERE DATE(t1.trade_timestamp) = '2014-04-28'

With the EXPLAIN statement you get:

  id    |   select_type |   table   |   type    |   possible_keys   |   key     |   key_len |   ref     |   rows    |   Extra
    1   |   SIMPLE      |   t1      |   ALL     |   NULL            |   NULL    |   NULL    |   NULL    |   943429  |   Using where
    1   |   SIMPLE      |  t2_inner |   ALL     |   NULL            |   NULL    |   NULL    |   NULL    |   943429  |   Using where; Using join buffer (flat, BNL join)

So the question is, how to make this query faster, joining the id with the id+1? If it's possible, i would like to go without a parent_id column.

Was it helpful?

Solution

Rewrite this query into:

SELECT ... (do the calculation with t1.trade_timesamp and t2.trade_timestamp) ...
FROM t_course_live t1
LEFT JOIN t_course_live t2
ON t1.id = t2.id+1
WHERE
  t1.trade_timestamp>= '2014-04-28'
  AND t1.trade_timestamp < '2014-04-29'
  and t2.trade_timestamp>= '2014-04-28'
  AND t2.trade_timestamp < '2014-04-29'

Using DATE(column) function and joinin with a subquery prevents MySql from using indexes.

I assume that an index on trade_timestamp has already been created.

=========== EDIT =========================

There is a subtle mistake in my previous answer.
The above query is not equivalent to the orginal query, because these conditions:

  and t2.trade_timestamp>= '2014-04-28'
  AND t2.trade_timestamp < '2014-04-29'

converts the query from left join into regular join.

A correct query is:

SELECT ... (do the calculation with t1.trade_timesamp and t2.trade_timestamp) ...
FROM t_course_live t1
LEFT JOIN t_course_live t2
ON t1.id = t2.id+1
   AND t2.trade_timestamp>= '2014-04-28'
   AND t2.trade_timestamp < '2014-04-29'
WHERE
  t1.trade_timestamp>= '2014-04-28'
  AND t1.trade_timestamp < '2014-04-29'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top