web-dev-qa-db-ja.com

SQLクエリをCASE / WHENでJoomlaベースの「形式」に書き換える方法

データベースへの次のSQLクエリがあります。

$jinput = JFactory::getApplication()->input;
$category_id = $jinput->get('virtuemart_category_id');
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query = 'SELECT b.`virtuemart_product_id`,
    (CASE 
        WHEN b.`product_override_price` > 0 THEN b.`product_override_price`
        WHEN b.`product_discount_id` > 0 THEN  b.`product_price` - (b.`product_discount_id` * b.`product_price` / 100)
        WHEN b.`product_price` < 1 THEN 1
        ELSE b.`product_price` 
        END) as final_price
    FROM #__virtuemart_product_categories as a
    LEFT JOIN #__virtuemart_product_prices as b ON b.`virtuemart_product_id` = a.`virtuemart_product_id`
    AND `virtuemart_category_id` = '.$category_id.'
    ORDER BY final_price ASC';
$db->setQuery($query);
$rows = $db->loadObjectList();

CASE、WHEN ... THEN ...で行をJoomlaベースの「フォーマット」に書き換える方法:

$query->select('a.virtuemart_product_id');
$query->from('#__virtuemart_product_categories AS a');
$query->where($db->quoteName('virtuemart_category_id')." = ".$db->quote($category_id));
... // ???
$query->join('LEFT', '#__virtuemart_...');
$query->order('final_price ASC');
4
stckvrw

この構文をお勧めします:

_$db = JFactory::getDBO();
try {
    $query = $db->getQuery(true)
                ->select(
                    array(
                        $db->qn('b.virtuemart_product_id'),
                        "CASE WHEN " . $db->qn('b.product_override_price') . " > 0" .
                            " THEN " . $db->qn('b.product_override_price') .
                            " WHEN " . $db->qn('b.product_discount_id') . " > 0" .
                            " THEN " . $db->qn('b.product_price') . " - (" . $db->qn('b.product_discount_id') . " * " . $db->qn('b.product_price') . " / 100)" .
                            " WHEN " . $db->qn('b.product_price') . " < 1" .
                            " THEN 1" .
                            " ELSE " . $db->qn('b.product_price') .
                            " END AS " . $db->qn('final_price')
                    )
                )
                ->from($db->qn('#__virtuemart_product_categories', 'a'))
                ->innerJoin($db->qn('#__virtuemart_product_prices', 'b') . " ON " . $db->qn('b.virtuemart_product_id') . " = " . $db->qn('a.virtuemart_product_id'))
                ->where($db->qn('a.virtuemart_category_id') . " = " . (int)$category_id)
                ->order($db->qn('final_price'));
    echo $query->dump();    // of course, don't do this on your live/public site
    $db->setQuery($query);
    echo "<pre>";
        var_export($db->loadObjectList());
    echo "</pre>";
} catch (Exception $e) {
    echo "<div>", $e->getMessage(), "</div>";  // of course, don't do this on your live/public site
}
_
  • qn()quoteName()のエイリアスであり、テーブル名、列名、およびそれらのエイリアスをバックティックラップするために使用されます。テーブルエイリアスを割り当てる場合は、qn()の2番目のパラメータとして書き込みます。
  • クエリ構造を少し変更し、_$category_id_をWHERE句に書き込みました-より適切で読みやすいと思うからです。
  • 私はgetQuery()からメソッドをチェーンすることを好みます-実行できるからです。
  • 視覚的には、CASEの構文は目の粗いものです。キーワードを並べて読みやすさを改善しようとしましたが、他の開発者は別のスタイルを好むかもしれません。
  • _(int)_は、セキュリティ上の予防措置として_$category_id_に適用されます。
  • try-catch()ブロックはデバッグ時に便利です。ライブサイトにクエリやエラーを表示しないでください。

Category_idが1の場合、レンダリングされたクエリは次のようになります(私はdump()値にタブを付けました)

_SELECT `b`.`virtuemart_product_id`,
       CASE WHEN `b`.`product_override_price` > 0 THEN `b`.`product_override_price`
            WHEN `b`.`product_discount_id` > 0 THEN `b`.`product_price` - (`b`.`product_discount_id` * `b`.`product_price` / 100)
            WHEN `b`.`product_price` < 1 THEN 1 ELSE `b`.`product_price`
            END AS `final_price`
FROM `vwxyz_virtuemart_product_categories` AS `a`
INNER JOIN `vwxyz_virtuemart_product_prices` AS `b` ON `b`.`virtuemart_product_id` = `a`.`virtuemart_product_id`
WHERE `a`.`virtuemart_category_id` = 1
ORDER BY `final_price`
_

そして最後に、これが動作することを証明する db-fiddle です。

2
mickmackusa
$query->select('a.virtuemart_product_id')
->from('#__virtuemart_product_categories AS a')
->select('(CASE WHEN '.$db->qn('b.product_override_price').' > 0 
THEN '.$db->qn('b.product_override_price').
' WHEN '.$db->qn('b.product_discount_id').' > 0 
THEN '.$db->qn('b.product_price').' - ('.$db->qn('b.product_discount_id').' * '.$db->qn('b.product_price').' / 100) 
WHEN '.$db->qn('b.product_price').' < 1 
THEN 1 ELSE '.$db->qn('b.product_price').' END)
as '.$db->qn('final_price'));
2
Alexandr

case/when/then構成のJoomlaベースの関数はありません。mysqlで単純な選択を使用する必要がありますその中のcaseステートメント

$query->select("(CASE ...) as final_price");

利用可能なデータベースJoomla関数の完全なリストについては、 JDatabaseQuery API を参照してください。

1
Kitase88