Maison >base de données >tutoriel mysql >FIND_IN_SET() vs IN() : quand dois-je utiliser chacun pour les valeurs séparées par des virgules ?

FIND_IN_SET() vs IN() : quand dois-je utiliser chacun pour les valeurs séparées par des virgules ?

DDD
DDDoriginal
2024-12-25 21:35:16894parcourir

FIND_IN_SET() vs. IN(): When Should I Use Each for Comma-Separated Values?

FIND_IN_SET() vs IN() : dévoilement de l'énigme des requêtes

Dans le domaine des requêtes de bases de données, comprendre les nuances entre les différentes fonctions est crucial. Une telle distinction apparaît lors de la comparaison de FIND_IN_SET() et IN(), en particulier lors de l'interrogation de valeurs stockées sous forme de chaînes séparées par des virgules.

L'écart de requête

Considérez deux tableaux : "commandes" avec une colonne "attachedCompanyIDs" contenant des identifiants d'entreprise séparés par des virgules et "company" avec une colonne "companyID" et les noms de sociétés correspondants. La requête suivante récupère efficacement les noms de sociétés associés à une commande à l'aide de FIND_IN_SET() :

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

Cependant, une requête similaire utilisant IN() donne des résultats inattendus :

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

Le piège caché

La cause première réside dans la façon dont MySQL gère les valeurs séparées par des virgules lors de la conversion des attachmentCompanyIDs en un entier. Le casting tronque les nombres au premier chiffre non-chiffre, réduisant ainsi la chaîne à la première valeur séparée par des virgules.

Par exemple, avec attachmentCompanyIDs défini sur « 1,2,3 », la requête IN() est incorrecte. devient :

companyID IN (1)

Cela explique pourquoi la requête IN() ne renvoie que le premier nom de l'entreprise, tandis que FIND_IN_SET() renvoie tous trois.

Surmonter les limitations

Pour résoudre ce problème, envisagez des approches alternatives qui gèrent de manière appropriée les chaînes séparées par des virgules. Dans PostgreSQL, les tableaux peuvent être utilisés :

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

Malheureusement, les tableaux ne sont pas pris en charge dans MySQL. Pour un nombre limité de valeurs (disons, moins de 5), une solution de contournement est possible en utilisant la jointure croisée et la manipulation de chaînes :

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)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn