web-dev-qa-db-fra.com

Comment récupérer les données de soumission RSForm groupées par SubmissionId?

J'ai une table avec 3 colonnes: SubmissionId, FieldName et FieldValue.

1) SubmissionId conserve la soumission de l'identifiant.

2) FieldName stocke le nom de champ d'un formulaire.

) FieldValue stocke la valeur du champ de formulaire.

J'ai un formulaire avec 3 champs: name, email et status. J'ai quatre soumissions, au total il y a 12 entrées: 3 par soumission.

Comment obtenir 3 enregistrements d'une soumission où le champ status de cette soumission est égal à la chaîne "open"?

C'est possible? Je la requête à suivre, mais évidemment, il ne récupère que l'enregistrement contenant le champ "status". J'ai besoin des 2 autres champs.

MIS À JOUR:

$query
    ->select('a.SubmissionId, a.DateSubmitted, a.status, b.SubmissionId, b.FieldName, b.FieldValue')
    ->from($db->quoteName('#__rsform_submissions', 'a'))
    ->join('INNER', $db->quoteName('#__rsform_submission_values', 'b') . ' ON (' . $db->quoteName('a.SubmissionId') . ' = ' . $db->quoteName('b.SubmissionId') . ')')
    ->where($db->quoteName('b.FieldName') . ' = \'status\' AND ' . $db->quoteName('b.FieldValue') . ' = \'open\'' );
2
George Berkeley

En réalité, vous n'avez pas besoin de faire plusieurs jointures avec la même table pour rassembler les résultats souhaités. Ce qui convient le mieux est une technique "pivot" . Il n'y a pas de moyen plus clair de traiter les données de soumission de rsform.

Veuillez noter que même si vous ne pouvez avoir qu'un seul "formulaire" dans votre table #__rsform_submissions, Il serait plus simple de spécifier le FormId dans la clause WHERE. (J'utiliserai volontiers 1 Dans mon extrait à suivre.)

La requête brute que je suggère est:

SELECT
    a.SubmissionId,
    a.DateSubmitted,
    a.status,
    MAX(CASE WHEN b.FieldName = 'name' THEN b.FieldValue ELSE NULL END) AS name,
    MAX(CASE WHEN b.FieldName = 'email' THEN b.FieldValue ELSE NULL END) AS email
FROM `#__rsform_submissions` a
INNER JOIN `#__rsform_submission_values` b ON a.SubmissionId = b.SubmissionId
WHERE a.FormId = 1
GROUP BY a.SubmissionId
HAVING MAX(CASE WHEN b.FieldName = 'status' THEN b.FieldValue ELSE NULL END) = 'open'

Ce qui précède joint les deux tables liées (une seule fois), puis regroupe les valeurs de soumission en fonction de SubmissionId. La clause GROUP BY crée des données "agrégées" (un nuage de données liées - si vous préférez) qui nécessitent un traitement spécial pour extraire les valeurs souhaitées. La syntaxe MAX(CASE...) vous permet d'extraire des valeurs spécifiques. La clause HAVING vérifie les soumissions qui ont une valeur status de open; la clause SELECT extrait les name et email à fournir dans le jeu de résultats.

Joomla/code PHP:

$query = $db->getQuery(true)
    ->select([
        "a.SubmissionId",
        "a.DateSubmitted",
        "a.status",
        "MAX(CASE WHEN b.FieldName = 'name' THEN b.FieldValue ELSE NULL END) AS name",
        "MAX(CASE WHEN b.FieldName = 'email' THEN b.FieldValue ELSE NULL END) AS email"
    ])
    ->from("#__rsform_submissions a")
    ->innerJoin("#__rsform_submission_values b ON a.SubmissionId = b.SubmissionId")
    ->where("a.FormId = 1")
    ->group("a.SubmissionId")
    ->having("MAX(CASE WHEN b.FieldName = " . $db->q("status") . " THEN b.FieldValue ELSE NULL END) = " . $db->q("open"));

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

Schéma de test:

CREATE TABLE IF NOT EXISTS `#__rsform_submissions` (
  `SubmissionId` int(11) NOT NULL,
  `FormId` int(11) NOT NULL DEFAULT '0',
  `DateSubmitted` datetime NOT NULL,
  `UserIp` varchar(15) NOT NULL DEFAULT '',
  `Username` varchar(255) NOT NULL DEFAULT '',
  `UserId` text NOT NULL,
  `Lang` varchar(255) NOT NULL,
  `status` tinyint(1) NOT NULL
) ENGINE=InnoDB CHARSET=utf8;

INSERT INTO `#__rsform_submissions` (`SubmissionId`, `FormId`, `DateSubmitted`, `UserIp`, `Username`, `UserId`, `Lang`, `status`) VALUES
(1, 1, '2011-01-01 01:11:11', '60.241.244.9', 'Cam', '0', 'en-GB', 1),
(2, 1, '2012-02-02 02:22:22', '203.59.245.124', 'Pam', '0', 'en-GB', 1),
(3, 1, '2013-03-03 03:33:33', '101.172.255.225', 'Sam', '0', 'en-GB', 1),
(4, 1, '2014-04-04 04:44:44', '55.79.10.25', 'Tam', '0', 'en-GB', 1);

CREATE TABLE IF NOT EXISTS `#__rsform_submission_values` (
  `SubmissionValueId` int(11) NOT NULL AUTO_INCREMENT,
  `FormId` int(11) NOT NULL,
  `SubmissionId` int(11) NOT NULL DEFAULT '0',
  `FieldName` text NOT NULL,
  `FieldValue` text NOT NULL,
  PRIMARY KEY (`SubmissionValueId`),
  KEY `FormId` (`FormId`),
  KEY `SubmissionId` (`SubmissionId`)
) ENGINE=InnoDB CHARSET=utf8;

INSERT INTO `#__rsform_submission_values` (`SubmissionValueId`, `FormId`, `SubmissionId`, `FieldName`, `FieldValue`) VALUES
(1, 1, 1, 'name', 'Cam'),
(2, 1, 1, 'email', '[email protected]'),
(3, 1, 1, 'status', 'open'),
(4, 1, 2, 'name', 'Pam'),
(5, 1, 2, 'email', '[email protected]'),
(6, 1, 2, 'status', 'closed'),
(7, 1, 3, 'name', 'Sam'),
(8, 1, 3, 'email', '[email protected]'),
(9, 1, 3, 'status', 'open'),
(10, 1, 4, 'name', 'Tam'),
(11, 1, 4, 'email', '[email protected]'),
(12, 1, 4, 'status', 'open');

Sortie:

array(3) {
  [0]=>
  array(5) {
    ["SubmissionId"]=>
    string(1) "1"
    ["DateSubmitted"]=>
    string(19) "2011-01-01 01:11:11"
    ["status"]=>
    string(1) "1"
    ["name"]=>
    string(3) "Cam"
    ["email"]=>
    string(13) "[email protected]"
  }
  [1]=>
  array(5) {
    ["SubmissionId"]=>
    string(1) "3"
    ["DateSubmitted"]=>
    string(19) "2013-03-03 03:33:33"
    ["status"]=>
    string(1) "1"
    ["name"]=>
    string(3) "Sam"
    ["email"]=>
    string(13) "[email protected]"
  }
  [2]=>
  array(5) {
    ["SubmissionId"]=>
    string(1) "4"
    ["DateSubmitted"]=>
    string(19) "2014-04-04 04:44:44"
    ["status"]=>
    string(1) "1"
    ["name"]=>
    string(3) "Tam"
    ["email"]=>
    string(13) "[email protected]"
  }
}
2
mickmackusa

Vous voilà:

$query->select($db->qn('s.SubmissionId','id'))
        ->select($db->qn('s.DateSubmitted','date'))
        ->select($db->qn('sv.FieldValue','status'))
        ->select($db->qn('nv.FieldValue','name'))
        ->select($db->qn('ev.FieldValue','email'))
        ->from($db->qn('#__rsform_submissions','s'))
        ->leftJoin($db->qn('#__rsform_submission_values','sv').' ON '.$db->qn('sv.SubmissionId').' = '.$db->qn('s.SubmissionId').' AND '.$db->qn('sv.FieldName').' = '.$db->q('status'))
        ->leftJoin($db->qn('#__rsform_submission_values','nv').' ON '.$db->qn('nv.SubmissionId').' = '.$db->qn('s.SubmissionId').' AND '.$db->qn('nv.FieldName').' = '.$db->q('name'))
        ->leftJoin($db->qn('#__rsform_submission_values','ev').' ON '.$db->qn('ev.SubmissionId').' = '.$db->qn('s.SubmissionId').' AND '.$db->qn('ev.FieldName').' = '.$db->q('email'))
        ->where($db->qn('sv.FieldValue').' = '.$db->q('open'));

En sortie, vous aurez une rangée avec les données dont vous avez besoin. Je crois que le code est assez facile à comprendre chaque ligne.

1
Alexandr