Mysql
 sql >> Base de données >  >> RDS >> Mysql

FIND_IN_SET() contre IN()

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

attachedCompanyIDs est une valeur scalaire qui est convertie en INT (type de companyID ).

Le casting ne renvoie que les nombres jusqu'au premier non-chiffre (une virgule dans votre cas).

Ainsi,

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

Dans PostgreSQL , vous pouvez convertir la chaîne en tableau (ou la stocker en tant que tableau en premier lieu) :

SELECT  name
FROM    orders
JOIN    company
ON      companyID = ANY (('{' | attachedCompanyIDs | '}')::INT[])
WHERE   orderID = 1

et cela utiliserait même un index sur companyID .

Malheureusement, cela ne fonctionne pas dans MySQL car ce dernier ne prend pas en charge les tableaux.

Vous trouverez peut-être cet article intéressant (voir #2 ):

Mise à jour :

S'il existe une limite raisonnable sur le nombre de valeurs dans les listes séparées par des virgules (par exemple, pas plus de 5 ), vous pouvez donc essayer d'utiliser cette requête :

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)