J'ai un varchar(255)
champ dans l'un de mes Jdatabase
tables contenant des valeurs séparées par des virgules . Justement, il contient des nombres séparés par des virgules.
Je veux récupérer les valeurs individuelles en utilisant un module personnalisé [~ # ~] php [~ # ~] . En fait, je dois sélectionner des enregistrements ( qui récupèrent des données ) à partir d'une autre table dont l'identifiant existe déjà dans la liste d'identifiants séparés par des virgules.
Quel serait le meilleur moyen d'y parvenir?
Juste 2 requêtes simples. Commencez par sélectionner des virgules, puis vérifiez si les identifiants se trouvent dans cette chaîne. Vient de tester et cela fonctionne avec la fonction MySql IN () avec la valeur de chaîne $commas
Extraite de $db->loadResult()
.
Rien ne peut être plus simple.
// First get all commas
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->qn('Commas'))
->from($db->qn('#__classes_attended'))
->where($db->qn('Id') . ' = 1');
$db->setQuery($query);
$commas = $db->loadResult();
// Select them from second table
$query = $db->getQuery(true);
$query->clear();
$query->select($db->qn('Data_needed'))
->from($db->qn('#__jdatabse_table_2'))
->where($db->qn('Id') . ' IN (' . $commas . ')');
$db->setQuery($query);
$results = $db->loadObjectList();
Quel serait le meilleur moyen d'y parvenir?
Il y a deux "bonnes pratiques" que je suis obligé de partager pour cette question.
Ne faites pas plus de voyages dans la base de données que nécessaire.
Étant donné que votre logique de requête peut être intégrée à une seule requête, elle devrait l'être. Le héros à utiliser dans cette instance est FIND_IN_SET () . Cela fonctionne de la même manière que IN
, mais IN
ne fonctionnera pas avec une valeur de colonne délimitée par des virgules .
Requête brute: ( démo db-fiddle.com )
SELECT name
FROM `#__table2`
WHERE FIND_IN_SET(id, (SELECT classes_attended FROM `#__table1` WHERE id = 1))
* Cela aurait pu être effectué en tant que JOIN au lieu d'une sous-requête (comme indiqué dans le lien stackoverflow au-dessus de mon extrait de code), mais je préfère cette approche car vous n'avez besoin de vous rapporter qu'à une seule ligne.
Syntaxe Joomla/PHP: (testée localement; inclut le vidage de la requête et la vérification des erreurs)
$id = 1;
try {
$db = JFactory::getDbo();
$subquery = $db->getQuery(true)
->select($db->qn("classes_attended"))
->from($db->qn("#__table1"))
->where($db->qn("id") . " = " . (int)$id);
$query = $db->getQuery(true)
->select($db->qn("name"))
->from($db->qn("#__table2"))
->where("FIND_IN_SET(" . $db->qn("id") . ", (" . $subquery . "))");
$db->setQuery($query);
JFactory::getApplication()->enqueueMessage($query->dump(), 'info'); // don't show your rendered query to the public
if (!$result = $db->loadColumn()) {
echo "<p>No Rows Found</p>";
} else {
echo "<pre>";
var_export($result); // prints indexed single-dimensional array of values
echo "</pre>";
}
} catch (Exception $e) {
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error'); // don't show $e->getMessage() to public
}
Normalisez votre structure de données.
Utiliser FIND_IN_SET()
est un symptôme indiquant que la conception de votre base de données n'est pas optimisée.
Ne prenez pas ma parole pour elle, écoutez Bill Karwin - un homme qui a littéralement écrit n livre sur les mauvaises pratiques de codage SQL .
Vous ne pouvez pas optimiser cette requête avec des index. C’est l’une des nombreuses raisons pour lesquelles stocker des listes de valeurs séparées par des virgules est une mauvaise idée dans une base de données relationnelle.
Source: https://stackoverflow.com/a/44183060/29434
Normaliser vos données dans ce cas signifie créer une nouvelle table et décomposer les données classes_attended
En lignes contenant id
et class_attended
. Cela facilitera l'interrogation de vos données et vous permettra de créer des requêtes plus complexes avec une plus grande efficacité.
id | classes_attended
-----------------------------------
1 | 1,3,6,7
devient
id | class_attended
---------------------------------
1 | 1
1 | 3
1 | 6
1 | 7
Voici le lien d'un débutant à propos de Normalisation .