2

I'm trying to run the following query, but it keeps getting "reduced" and failing. Cannot get MySQL to provide any information as to why.

Here's the query:

SELECT * FROM animals WHERE name IN(SELECT @animal_names);

Here's the information underneath the variable and table.

TABLE:

mysql> mysql> SELECT * FROM animals;
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
+----+---------+
6 rows in set (0.00 sec)

VARIABLE:

mysql> SELECT GROUP_CONCAT(QUOTE(name)) INTO @animal_names FROM animals WHERE name LIKE '%%';
Query OK, 1 row affected (0.01 sec)

mysql> mysql> SELECT @animal_names; +-----------------------------------------------+ | @animal_names | +-----------------------------------------------+ | 'dog','cat','penguin','lax','whale','ostrich' | +-----------------------------------------------+ 1 row in set (0.00 sec)

ISSUE:

mysql> SELECT * FROM animals WHERE name IN(SELECT @animal_names);
Empty set (0.00 sec)

mysql> EXPLAIN SELECT * FROM animals WHERE name IN(SELECT @animal_names); +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | animals | ALL | NULL | NULL | NULL | NULL | 6 | Using where | +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ 1 row in set, 1 warning (0.00 sec)

Note (Code 1249): Select 2 was reduced during optimization

MySQL refuses to tell me why the "SELECT @animal_ids" is not working! Is there some MySQL variable that needs to be adjusted for that subquery to work?

This is a test sample. I'm trying to do this on a larger scale with about 800 values in a list. I want the list in a variable so I don't have to do A SELECT query multiple times to DELETE, INSERT, SELECT the values I need across multiple databases and tables.

Obviously this can be easily done with a Python or Golang script, but I'm trying to do this in MySQL directly. While I appreciate it, please refrain from offering script-based solutions.

asked Apr 26, 2016 at 16:13

4 Answers 4

3

The variable contains ONE string, but to work properly the subquery in IN() needs to return different items as multiple rows.

SELECT * FROM animals WHERE name IN(SELECT @animal_names);

is translated to

SELECT * FROM animals WHERE name IN(SELECT '\'dog\',\'cat\',\'penguin\',\'lax\',\'whale\',\'ostrich\'');

MySQL variable cannot hold table resultset so this is not directly possible. You would have to create a subquery to extract separate values to rows by joining some counter table and parsing the string. Or you may use dynamic sql which allows to take a string and parse it - that way you would define new variable containing entire select with the IN list filled by your current variable, and then prepare a statement from that string representation (sort of SQL eval). But probably best would be to just use the query direcly as a subquery instead of filling the variable. Newer version should materialize such independent subquery automatically. For good performance on older versions, you might want to create a temporary table instead and use JOIN and not IN.

Just a note - GROUP_CONCAT() is not very safe as there is a limit (variable) to how long string it can return and some results may be lost (with a warning) when the limit is exceeded.

answered Apr 26, 2016 at 19:37
1
  • You can set your own limit to avoid losing results: SET SESSION group_concat_max_len = 10000; Commented May 13, 2024 at 13:24
0

You could do:

SELECT *
FROM animals
WHERE CONCAT(',', @animal_names, ',') LIKE CONCAT('%,\'', name, '\',%');

It won't perform fast, but it'll work.

answered Apr 27, 2016 at 5:59
2
  • May fail if the lists are sorted differently. Commented Apr 27, 2016 at 17:43
  • @RickJames It could only fail if the elements in the list could have commas next to apostrophes Commented Apr 27, 2016 at 22:44
0

Build a Stored Routine; in it use CONCAT to construct the SELECT with the @variable stitched in; prepare and execute.

Alternatively, if you are using an application language such as PHP, do the stitching in that language.

answered Apr 27, 2016 at 17:46
0
SELECT * FROM animals WHERE FIND_IN_SET(name,(SELECT @animal_names));

See the FIND_IN_SET documentation

Tom V
15.8k7 gold badges66 silver badges87 bronze badges
answered Apr 27, 2016 at 18:20
1
  • This is what I was trying to do. Commented Apr 29, 2016 at 20:25

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.