3

I am trying to use the results of a subquery in an IN query to return some results from a table based on some ids in a second table. The structure of Table1 is not important, but Table2 stores information like this:

other_ID  | members
1         | .10.,.16.,.86.
2         | .32.,.34.

other_ID is stored as INT while members is stored as TEXT. I didn't create the table structure, but my understanding is that members is stored in that format since it gets tricky storing variable-length CSVs in columns in a database. Either way, I'm not able to change the table structure.

I have the following query:

SELECT * FROM Table1 WHERE
Table1.ID IN (REPLACE((SELECT members FROM Table2 WHERE other_ID = 2), ".", ""));

Try as I might, the query only ever returns values from the first value in the members column (i.e. 32). If I try the following query:

SELECT * FROM Table1 WHERE Table1.ID IN (32,34);

The results are returned successfully.

Any ideas as to what I'm doing wrong?

6
  • 2
    can you put replace inside the select fields? like select replace(members,".","") Commented Jun 10, 2019 at 5:26
  • Hi sanjun, I started my query that way initially but it produced exactly the same results, so I figured I'd drop the SELECT statement as it didn't seem required. Commented Jun 10, 2019 at 5:31
  • are you getting all results without replace function? Commented Jun 10, 2019 at 5:33
  • Hi sanjun, I'm not sure exactly what you mean. If I don't use that replace function, then SELECT members FROM Table2 WHERE other_ID = 2 returns .32.,.34., which is not useable. Is that what you meant? Commented Jun 10, 2019 at 5:36
  • No, i just told u this to identify if the Replace function is making this issue Commented Jun 10, 2019 at 5:41

2 Answers 2

2

You could try using REGEXP here with a join:

SELECT t1.*
FROM Table1 t1
INNER JOIN Table2 t2
    ON t2.members REGEXP CONCAT('[[:<:]]', t1.ID, '[[:>:]]')
WHERE
    t2.other_ID = 2;

The regex logic used above would compare this members string:

.32.,.34.

against a regex which looks like this:

\b34\b

This should work, as the commas/dots surrounding each number in members form a word boundary.

Note that the best long term fix here would be to not store your data in unnormalized CSV format.

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

3 Comments

That worked! Thank you! Could you please explain to me why my query doesn't work? Also, from my (very cursory) inspection, your query takes about 10 times longer to return a result (I suspect because of the JOIN). Is there no way to write my original query not using a JOIN?
The WHERE IN clause needs to be followed by a CSV list of columns, not a text CSV list. My query takes a while because we are invoking a regex engine for each join condition. To avoid this penalty, consider normalizing your table, and get ID onto a separate row.
OK great, thanks very much for the explanation Tim.
1

REPLACE((SELECT members FROM Table2 WHERE other_ID = 2), ".", "")

this will not work because it will take as single number you have to split that string as below. This worked for me

select * from IS_ACC_ACTIVITY_ERROR_LOGS where ERROR_LOG_ID IN( select regexp_substr ((SELECT REPLACE(ERROR_DESCRIPTION,'.','') des FROM IS_ACC_ACTIVITY_ERROR_LOGS WHERE ERROR_LOG_ID = 2), '[^,]+', 1, rn) as splited_string from dual cross join (select rownum as rn from dual connect by level <= 2))

1 Comment

Hi there, unfortunately your code doesn't use the parameters I've supplied in my original question. Also, I'm using MySQL 5.6 which doesn't support REGEXP_SUBSTR.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.