web-dev-qa-db-ja.com

RSForm送信データの2つの選択クエリをリファクタリングするにはどうすればよいですか?

複数のクエリを1つのクエリに結合するのを手伝ってくれる人がいるかどうか疑問に思っていました。現在、これらの2つのコードブロックは、DBから情報を取得します。 「Sourcerer」プラグインを使用して、カスタムモジュールにカスタムPHPコードを追加します。

ただし、クエリ全体が長すぎるため、サイズを大幅に削減する必要があります。一定量のクエリの後、ページがまったく読み込まれません。

例として、参加する必要がある2つのクエリを投稿します。

<?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

MySql構文を確認したかったので、結果の内破の代わりに(1,2,3)を使用したmySQLクエリをここに示します。 PHPに今すぐ変換する時間はありませんが、手助けしたいと思っていました。それがうまくいかない場合は、コメントで知らせてください、そして調整しようとします:

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;

StackExchangeを正しくフォーマットするためにチェックマークを削除する必要がありましたが、とにかく$ db-> quoteと$ dbquotenameを使用するようにコードを変換することをお勧めします: https://docs.joomla .org/Selecting_data_using_JDatabase
https://docs.joomla.org/Secure_coding_guidelines

2
YellowWebMonkey

はい、クエリはリファクタリングを使用できます。同じテーブルで2つの別々の呼び出しを使用することは、MySQLに不要な追加作業を要求することになります。

クエリをわかりやすい英語に変換するには、次のようにします。

  • SubmissionIdでソートされた_containertype1_値の結果セットを作成する
  • SubmissionIdからFormId _28_
  • Pendingの_Status1_値を含む提出のみを含みます。

このタスクを実行する最もクリーンで最も直接的な方法は、「ピボット」手法を使用することです。

生のクエリ(テストされていない):

_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_は、一意のSubmissionIdごとに「集約データ」を作成します。この統合された行のコレクション内から特定の詳細を抽出するには、特殊な呼び出し(MAX(CASE...)など)が必要です。

HAVING句では、SubmissionIdにFieldNameが_Status1_で、FieldValueの値がPendingの行を含める必要があります。これは、submission_valuesテーブルでは、SubmissionIdに2つ以上の_Status1_行を含めることができないという事実に依存しています。

条件を満たすすべてのSubmissionIdについて、結果セットは_containertype1_で保存された値を提供します。対象のSubmissionIdに_containertype1_行がない場合、NULL値がデフォルトとして提供されます(必要に応じて、NULLを_No Container Type_に変更できます)。

PHP/Joomla構文(テストされていません):

_$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
}
_

この手法を他のコンテキストで確認したい場合は、ここに私が投稿した他のピボットソリューションをいくつか示します。

1
mickmackusa