Maison >base de données >tutoriel mysql >FIND_IN_SET() vs IN() : pourquoi l'un renvoie-t-il tous les résultats alors que l'autre ne renvoie que le premier ?
FIND_IN_SET() vs IN() : Comprendre l'écart dans les résultats des requêtes
Lors de l'interrogation de bases de données relationnelles, il est nécessaire de comprendre la distinction entre les fonctions FIND_IN_SET() et IN(). Cet article examine leur comportement dans un scénario de base de données spécifique.
Problème :
Considérez deux tableaux : les commandes et l'entreprise. La table des commandes comprend une colonne attachmentCompanyIDs qui contient une liste d'ID d'entreprise séparés par des virgules. La table des sociétés contient les noms réels des sociétés. Lors de l'exécution d'une requête pour récupérer les noms de sociétés associés à une commande à l'aide de la fonction FIND_IN_SET(), elle renvoie tous les résultats attendus. Cependant, remplacer FIND_IN_SET() par IN() dans la requête renvoie uniquement le premier nom de la société.
Cause :
La fonction IN() interprète les attachmentCompanyIDs comme un seul entier, alors que FIND_IN_SET() le traite comme une chaîne. Lorsque attachmentCompanyIDs est converti en nombre entier, il conserve uniquement les chiffres jusqu'au premier caractère non numérique (la virgule). Par conséquent, la requête IN() renvoie uniquement l'entreprise associée au premier numéro de la liste séparée par des virgules.
Solution :
Pour contourner ce problème, PostgreSQL propose une solution plus robuste :
SELECT name FROM orders JOIN company ON companyID = ANY(('{' || attachedCompanyIDs || '}')::INT[]) WHERE orderID = 1;
Cette requête exploite la fonction ANY() pour convertir les attachmentCompanyIDs sous forme de tableau, permettant une utilisation efficace d'un index sur companyID.
Mise à jour :
Pour les bases de données MySQL, qui ne prennent pas en charge les tableaux, une approche alternative peut être utilisée :
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);
Cette requête parcourt les positions potentielles, extrayant les sous-chaînes des attachmentCompanyID pour correspondre à l'ID de l'entreprise. Cela implique plusieurs jointures, mais cela reste fonctionnel pour les scénarios avec un nombre limité d'identifiants d'entreprise dans la liste séparée par des virgules.
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!