Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

FIND_IN_SET() vs IN()

SELECT  name
FROM    orders,company
WHERE   orderID = 1
        AND companyID IN (attachedCompanyIDs)

attachedCompanyIDs é um valor escalar que é convertido em INT (tipo de companyID ).

A conversão só retorna números até o primeiro não dígito (uma vírgula no seu caso).

Por isso,
companyID IN ('1,2,3') ≡ companyID IN (CAST('1,2,3' AS INT)) ≡ companyID IN (1)

Em PostgreSQL , você pode converter a string em array (ou armazená-la como um array em primeiro lugar):
SELECT  name
FROM    orders
JOIN    company
ON      companyID = ANY (('{' | attachedCompanyIDs | '}')::INT[])
WHERE   orderID = 1

e isso usaria até mesmo um índice em companyID .

Infelizmente, isso não funciona em MySQL já que o último não suporta arrays.

Você pode achar este artigo interessante (veja #2 ):

Atualização:

Se houver algum limite razoável no número de valores nas listas separadas por vírgulas (digamos, não mais que 5 ), então você pode tentar usar esta consulta:
SELECT  name
FROM    orders
CROSS JOIN
        (
        SELECT  1 AS pos
        UNION ALL
        SELECT  2 AS pos
        UNION ALL
        SELECT  3 AS pos
        UNION ALL
        SELECT  4 AS pos
        UNION ALL
        SELECT  5 AS pos
        ) q
JOIN    company
ON      companyID = CAST(NULLIF(SUBSTRING_INDEX(attachedCompanyIDs, ',', -pos), SUBSTRING_INDEX(attachedCompanyIDs, ',', 1 - pos)) AS UNSIGNED)