Search code examples
mysqlgroup-concat

MySQL - is it possible to use group_concat in an IN() statement?


I've been trying to use "group_concat" to build a list of values for use in IN(), but even carefully crafting a comma delimited, single-quoted value string doesn't seem to work. The following does not "find" "fr" in the group_concat'ed list, even though the displayed value for the group_concat is 'de','es','fr', and a result set of one record is incorrectly returned;

SELECT Message, table_id FROM Tenant
LEFT JOIN Translation on Translation.table_id=Tenant.ID
WHERE table_name='Tenant' AND table_column='Message' AND Tenant.ID=2
GROUP BY table_name, table_column, table_id HAVING 'fr' NOT 
IN(group_concat(CONCAT('''', language, '''')));

Whereas below, "fr" IS indeed found and the resultset is appropriately empty:

SELECT Message, table_id FROM Tenant
LEFT JOIN Translation on Translation.table_id=Tenant.ID
WHERE table_name='Tenant' AND table_column='Message' AND Tenant.ID=2
GROUP BY table_name, table_column, table_id HAVING 'fr' NOT IN('de','es','fr')

I realize I can use LOCATE();

SELECT Message, table_id FROM Tenant
LEFT JOIN Translation on Translation.table_id=Tenant.ID
WHERE table_name='Tenant' AND table_column='Message' AND Tenant.ID=2
GROUP BY table_name, table_column, table_id HAVING LOCATE('de', 
group_concat(language)) = 0

But such a text search is likely less efficient compared to "IN()", which is likely scheduled differently by the MySQL optimizer.

I've tried every trick I'm aware of (cast(), trying to reconstitute the list, etc) and I'm fresh out. I'm not sure if this is a limit of group_concat, or perhaps even a "bug" in MySQL compiler. If anyone has any good ideas, I'd be most appreciative.

Thanks


Solution

  • You should be using conditional aggregation in your HAVING clause to check for the French language string:

    SELECT
        table_id
    FROM Tenant
    LEFT JOIN Translation
        ON Translation.table_id = Tenant.ID
    WHERE
        table_name = 'Tenant' AND
        table_column = 'Message' AND
        Tenant.ID = 2
    GROUP BY
        table_id
    HAVING SUM(CASE WHEN language = 'fr' THEN 1 ELSE 0 END) = 0
    

    Note that I removed the table_name and table_column from the GROUP BY list, because you specify fixed values for these columns in the WHERE clause. Also, I removed Message from the SELECT list because it does not appear in the group by nor is it inside an aggregate function. Your original query would not even run on certain versions of MySQL or most other databases.