web-dev-qa-db-fra.com

Comment associer des identifiants séparés par des virgules d'une table aux identifiants d'une autre table?

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.

Table 1

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.

enter image description here

Quel serait le meilleur moyen d'y parvenir?

3
saibbyweb

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();
4
Adam M.

Quel serait le meilleur moyen d'y parvenir?

Il y a deux "bonnes pratiques" que je suis obligé de partager pour cette question.

  1. 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
    }
    
  2. 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 .

0
mickmackusa