How can I speed up this query:
SELECT
( select field_a1
from tableTen a2
where week(a1.date) = week(a2.date)
and substr(a1.date,1,4) = substr(a2.date,1,4)
and a2.time >= 0900
AND a2.time <= 1730
order by date asc, time asc limit 1
) as fieldValue_a1,
MAX(field_a2) as fieldValue_a2,
MIN(field_a3) as fieldValue_a3,
( select field_a4
from tableTen a2
where week(a1.date) = week(a2.date)
and substr(a1.date,1,4) = substr(a2.date,1,4)
and a2.time >= 0900
AND a2.time <= 1730
order by date desc, time desc limit 1
) as fieldValue_a4,
SUM(field_a5) as fieldValue_a5,
date,
time
FROM tableTen a1
WHERE date >= date_sub(STR_TO_DATE(20160829,'%Y%m%d'), interval 200.0 week)
and time >= 0900 AND time <= 1730
GROUP BY week(date), substr(date,1, 4)
ORDER BY date DESC
tableTen is:
+---------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| symbol | varchar(25) | YES | | NULL | |
| date | char(8) | YES | | NULL | |
| time | char(4) | YES | MUL | NULL | |
| fieldValue_a1 | double | YES | | NULL | |
| fieldValue_a2 | double | YES | | NULL | |
| fieldValue_a3 | double | YES | | NULL | |
| fieldValue_a4 | double | YES | | NULL | |
| fieldValue_a5 | int(11) | YES | | NULL | |
+---------------+-------------+------+-----+---------+-------+
the index are
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tableTen | 1 | ten_full_idx | 1 | time | A | 581 | NULL | NULL | YES | BTREE | | |
| tableTen | 1 | ten_full_idx | 2 | date | A | 593931 | NULL | NULL | YES | BTREE | | |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Explain query gives
+----+--------------------+-------+------+--------------+------+---------+------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys| key | key_len | ref | rows | Extra |
+----+--------------------+-------+------+--------------+------+---------+------+--------+----------------------------------------------+
| 1 | PRIMARY | a1 | ALL | ten_full_idx | NULL | NULL | NULL | 594441 | Using where; Using temporary; Using filesort |
| 3 | DEPENDENT SUBQUERY | a2 | ALL | ten_full_idx | NULL | NULL | NULL | 594441 | Using where; Using filesort |
| 2 | DEPENDENT SUBQUERY | a2 | ALL | ten_full_idx | NULL | NULL | NULL | 594441 | Using where; Using filesort |
+----+--------------------+-------+------+--------------+------+---------+------+--------+----------------------------------------------+
Table status
+----------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+----------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+
| tableTen | MyISAM | 10 | Dynamic | 594441 | 62 | 37389700 | 281474976710655 | 5325824 | 0 | NULL | 2016-08-29 19:41:47 | 2016-08-30 17:49:24 | 2016-08-29 19:41:49 | latin1_swedish_ci | NULL | | |
+----------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+
The field date contains date in format aaaammdd ex.: 20141027
The field time contains time in format hhmm ex.: 0809
A select requires about 4 minutes in a table with about 600000 rows.
How can I speed up the query ?
Update:
After the advice given to me by @dnoeth and @Andriy M I have inserted new field, my_date and my_time with correct data types, DATE and TIME using these queries:
ALTER TABLE tableTen ADD my_date date;
ALTER TABLE tableTen ADD my_time time;
UPDATE tableTen SET my_date = STR_TO_DATE(date,'%Y%m%d');
UPDATE tableTen SET my_time = STR_TO_DATE(time, '%H%i');
then I've created a new index, ten_idx:
+---------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tableTen | 1 | ten_full_idx | 1 | time | A | 582 | NULL | NULL | YES | BTREE | | |
| tableTen | 1 | ten_full_idx | 2 | date | A | 595482 | NULL | NULL | YES | BTREE | | |
| tableTen | 1 | ten_idx | 1 | my_date | A | 1158 | NULL | NULL | YES | BTREE | | |
| tableTen | 1 | ten_idx | 2 | my_time | A | 595482 | NULL | NULL | YES | BTREE | | |
+---------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
After the advice given to me by @dnoeth please refer your answers to the following query and not to the previous:
SELECT
a2.field_a1,
fieldValue_a2,
fieldValue_a3,
a3.field_a4,
fieldValue_a5,
maxDate,
maxTime
FROM
(
SELECT
-- min/max values for following joins (if they're not unique you might add another GROUP BY in the outer Select
-- this will add the time as "minutes & seconds" instead of "hours & minutes", but the next step will extract it correctly
DATE(MIN(TIMESTAMP(my_date,my_time))) as minDate,
TIME(MIN(TIMESTAMP(my_date,my_time))) as minTime,
DATE(MAX(TIMESTAMP(my_date,my_time))) as maxDate,
TIME(MAX(TIMESTAMP(my_date,my_time))) as maxTime,
MAX(field_a2) as fieldValue_a2,
MIN(field_a3) as fieldValue_a3,
SUM(field_a5) as fieldValue_a5
FROM tableTen
WHERE my_date >= date_sub(DATE '2016-08-29', interval 200.0 week)
and my_time BETWEEN TIME '09:00:00' AND TIME '17:30:00'
GROUP BY week(my_date), year(my_date)
) as a1
left join tableTen a2 -- minimum timestamp within week
on a1.minDate = a2.my_date
and a1.minTime = a2.my_time
left join tableTen a3 -- maximum timestamp within week
on a1.maxDate = a3.my_date
and a1.maxTime = a3.my_time
ORDER BY maxDate DESC
Once the work is completed I will remove the fields date and time of type char and its index.