web-dev-qa-db-fra.com

Comment refactoriser deux requêtes sélectionnées sur les données de soumission RSForm?

Je me demandais si quelqu'un pourrait m'aider à joindre plusieurs requêtes en une requête. Actuellement, ces 2 blocs de code extraient des informations de la base de données. J'utilise le plugin "Sourcerer" pour ajouter du code personnalisé PHP dans mon module personnalisé.

Cependant, la requête complète est beaucoup trop longue et je dois réduire considérablement sa taille. Après un certain nombre de requêtes, la page ne se charge plus du tout.

Je vais poster deux requêtes que je dois avoir rejoint à titre d'exemple.

<?php 
$db = JFactory::getDbo();
$db->getQuery(true);

$db->setQuery("SELECT `SubmissionId`, `FieldValue`, `FormId` FROM `jos_rsform_submission_values` WHERE `FieldName` = \"Status1\" AND `FieldValue` = \"Pending\" AND `FormId` = 28");
$results = $db->loadColumn();

$db->getQuery(true);
$db->setQuery("SELECT `FieldValue` FROM `jos_rsform_submission_values` WHERE `FieldName` = \"Container1\" AND `SubmissionId` IN ('".implode("', '", $results)."') ORDER BY `jos_rsform_submission_values`.`SubmissionId`"); 

$result = $db->loadObjectList();

foreach($result as $value) {
    foreach($value as $key => $data) { 
        echo $data."<br />"; 
    }
}
?>
1
MailBlade

Voici ce que je crois que la requête mySQL a été remplacée par (1,2,3) pour votre implosion de résultats parce que je voulais vérifier la syntaxe mySql de celle-ci. Je n'ai pas le temps de convertir en PHP pour le moment, mais je voulais essayer de vous aider. Si cela ne fonctionne pas, faites-le-moi savoir en commentaires et j'essaierai de régler:

SELECT a.FieldValue as Container, b.FieldValue as ContainerType FROM ( SELECT FieldValue FROM jos_rsform_submission_values WHERE FieldName = "Container1" AND SubmissionId IN (1,2,3)) as a LEFT JOIN ( SELECT FieldValue FROM jos_rsform_submission_values WHERE FieldName = "containertype1" AND SubmissionId IN (1,2,3)) as b on a.SubmissionId = b.SubmissionId ORDER BY a.SubmissionId;

J'ai dû supprimer les repères pour que StackExchange soit correctement formaté, mais je suggèrerais de convertir votre code pour utiliser $ db-> quote et $ dbquotename à la place de toute façon: https: //docs.joomla .org/Selecting_data_using_JDatabase
https://docs.joomla.org/Secure_coding_guidelines

2
YellowWebMonkey

Oui, vos requêtes peuvent certainement utiliser le refactoring. Utiliser deux appels séparés sur la même table demande à MySQL de faire un travail supplémentaire inutile.

Pour convertir vos requêtes en anglais clair, vous souhaitez:

  • créer un ensemble de résultats de containertype1 valeurs triées par SubmissionId
  • pour chaque SubmissionId de FormId28
  • comprenant uniquement les soumissions contenant une valeur Status1 de Pending.

La méthode la plus directe et la plus directe pour effectuer cette tâche consiste à utiliser une technique de "pivot".

Requête brute (non testée):

SELECT
    MAX(CASE WHEN FieldName = 'containertype1' THEN FieldValue ELSE NULL END)
FROM `#__rsform_submission_values`
WHERE FormId = 28
GROUP BY SubmissionId
HAVING MAX(CASE WHEN FieldName = 'Status1' THEN FieldValue ELSE NULL END) = 'Pending'
ORDER BY SubmissionId

GROUP BY Crée des "données globales" pour chaque unique SubmissionId. Pour extraire des détails spécifiques de cette collection de lignes consolidées, des appels spécialisés sont nécessaires (par exemple .MAX(CASE...)).

La clause HAVING requiert que SubmissionIds contienne une ligne avec un FieldName de Status1 Et une FieldValue valeur de Pending. Cela repose sur le fait que votre table submission_values ​​ne permet pas à un SubmissionId d'avoir deux lignes ou plus Status1.

Pour chaque SubmissionId éligible, le jeu de résultats fournira la valeur stockée avec containertype1. Si le SubmissionId éligible n’a pas de ligne containertype1, Une valeur NULL sera fournie par défaut (vous pouvez remplacer NULL par No Container Type Si vous le souhaitez. ).

Syntaxe PHP/Joomla (non testée):

$query = $db->getQuery(true)
    ->select("MAX(CASE WHEN FieldName = 'containertype1' THEN FieldValue ELSE NULL END)")
    ->from("#__rsform_submission_values")
    ->where("FormId = 28")
    ->group("SubmissionId")
    ->having("MAX(CASE WHEN FieldName = " . $db->q("status") . " THEN FieldValue ELSE NULL END) = " . $db->q("pending"));

// echo $query->dump();  // uncomment if you want to confirm the rendered query
try {
    $db->setQuery($query);
    echo "<pre>";
    var_dump($db->loadColumn());
} catch (Exception $e) {
    JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');  // never show getMessage() to public
}

Si vous souhaitez voir cette technique dans d'autres contextes, voici d'autres solutions pivots que j'ai publiées:

1
mickmackusa