0

I have a long table with stock prices that, among other fields, includes the following:

|    Date    |    exchange_code    |    ticker    |    price    |
|------------|---------------------|--------------|-------------|
|2020 -01-01 |         US          |    GOOG      |    XXXXX    |

I would like to know which is the most efficient way to select rows where pairs (exchange_code and ticker) are included in a given array.

The only idea I have is to add another column like exchange_ticker and then use a query like

SELECT * FROM mytable 
WHERE exchange_ticker IN (X,Y,Z);

Also, as the table is quite long, I would add an index over this column.

I'm sure there must be a better way... any idea?

Thanks!

2 Answers 2

2

You can use tuples:

SELECT *
FROM mytable 
WHERE (exchange, ticker) IN ( (A, X), (B, Y), (C, Z) );

This should be able to take advantage of an index on mytable(exchange, ticker).

If the list is already in a table, you can use JOIN:

select t.*
fro mytable t join
    list l
    using (exchange, ticker);

You also want an index for this as well.

Sign up to request clarification or add additional context in comments.

1 Comment

It should, but it won't - at least not prior to 8.0 :-(
0

GL's idea is a nice one but (at least in older versions of MySQL) it's not going to help much...

mysql> EXPLAIN
    -> SELECT *
    -> FROM mytable
    -> WHERE (exchange_code, ticker) IN ( ('US','MOBI'), ('US','TESL'), ('UK','BP') );
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | mytable | ALL  | NULL          | NULL | NULL    | NULL |  147 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN
    -> SELECT *
    ->   FROM mytable
    ->  WHERE (exchange_code = 'US' AND ticker = 'MOBI')
    ->     OR (exchange_code = 'US' AND ticker = 'TESL')
    ->     OR (exchange_code = 'UK' AND ticker = 'BP')
    ->     ;
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | mytable | ALL  | exchange_code | NULL | NULL    | NULL |  147 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.6.21    |
+-----------+

The second query doesn't use the index because my data set is tiny. The first query doesn't even find the index.

If I increase the size of the data set (and the cardinality of exchange_code) slightly, the difference becomes more pronounced.

mysql> EXPLAIN
    -> SELECT *
    ->   FROM mytable
    ->  WHERE (exchange_code = 'US' AND ticker = 'MOBI')
    ->     OR (exchange_code = 'US' AND ticker = 'TESL')
    ->     OR (exchange_code = 'UK' AND ticker = 'BP')
    ->     ;
+----+-------------+---------+-------+---------------+---------------+---------+------+------+-----------------------+
| id | select_type | table   | type  | possible_keys | key           | key_len | ref  | rows | Extra                 |
+----+-------------+---------+-------+---------------+---------------+---------+------+------+-----------------------+
|  1 | SIMPLE      | mytable | range | exchange_code | exchange_code | 16      | NULL |   43 | Using index condition |
+----+-------------+---------+-------+---------------+---------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN
    -> SELECT *
    -> FROM mytable
    -> WHERE (exchange_code, ticker) IN ( ('US','MOBI'), ('US','TESL'), ('UK','BP') );
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | mytable | ALL  | NULL          | NULL | NULL    | NULL | 2352 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.