web-dev-qa-db-fra.com

JDatabase JOIN sur plusieurs valeurs

Quelle est la syntaxe de JDatabase pour une instruction JOIN qui joint deux tables sur une variable égale à x ou nulle? Par exemple, il rejoint plusieurs valeurs.

J'ai trouvé quelques exemples qui me montrent que vous pouvez faire cela dans SQL normal mais je ne sais pas comment cela se traduit par la syntaxe JDatabase.

Ma requête fonctionne actuellement lorsque la variable (a.animal) est égale à b.id, mais j'ai besoin qu'elle soit également associée lorsque la variable (a.animal) est vide.

$query1 = $db->getQuery(true)
    ->select ($db->quoteName(array('a.date','a.reminder','a.type','a.animal','a.mob')))
    ->select ($db->quoteName('b.nameandid') .'AS'. $db->quote('animalname'))    
    ->from ($db->quoteName('app_reminders', 'a'))    
    ->join('INNER', $db->quoteName('app_animal', 'b') . 'ON (' .$db->quoteName('a.animal'). 'LIKE' .$db->quoteName('b.id').')')
    ->where ($db->quoteName('a.date') . '>=' . 'NOW()', 'AND')    
    ->where ($db->quoteName('a.user_id') . 'LIKE' . $db->quote($userid));
3
Hannah Smith

Dans votre instruction ON, vous devriez pouvoir ajouter plusieurs conditions combinées par AND et OR. Donc, quelque chose comme ceci devrait faire l'affaire:

->join('INNER', $db->quoteName('app_animal', 'b') . 'ON (' .$db->quoteName('a.animal'). 'LIKE' .$db->quoteName('b.id').' OR ' . $db->quoteName('a.animal') . ' IS NULL)')
3
fruppel

J'ai quelques préoccupations et améliorations à apporter, mais je vais tout d'abord passer directement au code et expliquer ensuite.

Vous voulez générer une requête qui se présente comme ceci:

SELECT a.date, a.reminder, a.type, a.animal, a.mob, b.nameandid AS 'animalname'
FROM app_reminders a
LEFT JOIN app_animal b ON a.animal = b.id
WHERE a.date >= NOW() AND a.user_id = 3

Notez que mon JOIN et le JOIN de la question de votre page StackOverflow liée utilisent LEFT JOIN. Le PO sur cette question ne veut que des lignes avec des valeurs dans toutes les tables jointes. La réponse utilise JOIN (jointure régulière aka INNER JOIN). Cela ignore les lignes contenant null pour la valeur de la jointure.

Vous voulez quelque chose de différent. Vous souhaitez que les lignes de la première table, que la seconde contienne ou non une valeur qualificative à joindre sur la ligne. Pour cela, vous voulez LEFT JOIN. Voici une démonstration de SQLFiddle si vous voulez jouer et comparer les résultats des jointures. (Si ce n'est pas l'action que vous recherchez, vous devriez pouvoir utiliser ce lien pour exprimer ce qui ne va pas.) Avec LEFT JOIN, Vous n'avez pas besoin d'ajouter la condition supplémentaire pour vérifier IS NULL.

En plus ...

  1. Vous utilisez l'opérateur LIKE mais sans les caractères génériques % Ou _, Il n'y a donc aucune raison d'écrire LIKE. Simplifiez simplement jusqu'à =.
  2. Alors que date et type sont mysql [~ # ~] mots-clés [~ # ~] , ils ne le sont pas MOTS-CLÉS RÉSERVÉS afin qu'ils ne soient pas obligés d'être emballés dans des backticks. Ceci est également vrai pour toutes vos autres colonnes et les noms de tables. Vous êtes invités à utiliser qn()/quoteName() sur toutes ces entités, mais cela ne fera qu'ajouter une surcharge à la syntaxe et au code de votre requête.
  3. Pour que votre requête soit plus lisible par l'homme, incluez un seul espace des deux côtés de vos opérateurs de comparaison. (par exemple, 'LIKE' est meilleur que ' LIKE ')
  4. Par mesure de sécurité, convertissez votre variable $userid Sous la forme d'un entier (int) Lorsque vous l'appliquez à votre requête. Il n'est pas nécessaire de citer les valeurs entières.
  5. Par souci de préférence personnelle et dans le but d’améliorer la lisibilité/la compréhension du code, j’essaie d’éviter d’utiliser des appels de méthode en double comme technique de concaténation pour une seule clause. Mon extrait de code Joomla suggéré utilisera un seul appel select() et un where(). (Lors de la jonction de plusieurs tables, la présence de plusieurs appels join() est logique/intuitive.)

Syntaxe Joomla (aucune méthode de citation appelée):

$query = $db->getQuery(true)
            ->select("a.date, a.reminder, a.type, a.animal, a.mob, b.nameandid AS 'animalname'")
            ->from("app_reminders a")
            ->joinLeft("app_animal b ON a.animal = b.id")
            ->where("a.date >= NOW() AND a.user_id = " . (int)$userid);

p.s. Si vous voulez réellement utiliser LIKE avec un ou plusieurs caractères génériques, , cet article vous montrera le moyen sécurisé - provenant de la Documentation Joomla.

1
mickmackusa