web-dev-qa-db-ja.com

Joomla 2.5、クエリオブジェクトを使用して「HAVING」を使用する方法

"SELECT *, ((ACOS(SIN($lat * PI() / 180) * SIN(latitude * PI() / 180) + COS(78 * PI() / 180) * COS(latitude * PI() / 180) * COS((87 - longitude) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance "
            . "FROM `#__content` AS `b` "
            . "RIGHT JOIN `#__jreviews_content` AS `a` ON (`a`.`contentid` = `b`.`id`) "
            . "LEFT JOIN `#__categories` AS `c` ON (`b`.`catid` = `c`.`id`) "
            . "LEFT JOIN `#__jreviews_media` AS `m` ON (`m`.`listing_id` = `b`.`id` AND `m`.`main_media` = 1 AND `m`.`media_type` = 'photo') "
            . "WHERE 1 = 1 AND (`c`.`title`  LIKE '%Stores%' OR `c`.`title`  LIKE '%Dining%' OR `c`.`title`  LIKE '%Events%') AND `a`.`jr_latitude`<> 0.0000000 AND `c`.`title`<> 'Archives' "
            . "HAVING distance<='50' "
            . "ORDER BY distance ASC"

HAVINGなしでQuery Objectを使用してクエリを作成できました

$query->select(array('*', '((ACOS(SIN($lat * PI() / 180) * SIN(latitude * PI() / 180) + COS(78 * PI() / 180) * COS(latitude * PI() / 180) * COS((87 - longitude) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance'))
                ->from($content)
                ->join('RIGHT', $jreviews_content . ' ON (' . $db->quoteName('a.contentid') . ' = ' . $db->quoteName('b.id') . ')')
                ->join('LEFT', $categories . ' ON (' . $db->quoteName('b.catid') . ' = ' . $db->quoteName('c.id') . ')')
                ->join('LEFT', $media . ' ON (' . $db->quoteName('m.listing_id') . ' = ' . $db->quoteName('b.id') . ' AND ' . $db->quoteName('m.main_media') . ' = 1 AND ' . $db->quoteName('m.media_type') . ' = "photo")')
                ->where($conditions);

このQuery ObjectHAVINGを書くのを手伝ってください

2
Siva.G ツ

Group_byなしでhaving句を使用している場合、where句と同じように動作します。

JDatabaseQueryクラスは、having句のメソッドを提供します。

これを試して

$query->having('distance <=50');
4
Nick

投稿されたクエリにいくつかの絞り込みを追加したい...

  • 有効ではありますが、JOINのON式ではなくWHERE句で条件付きフィルターを作成することをお勧めします。このように読むとわかりやすくなります。
  • 3つの個別のLIKE条件を作成するのではなく、3つの対象部分文字列を圧縮した1つのREGEXP条件を作成する方が簡単です。
  • 1 = 1にメリットはありません
  • 「より重い」条件の前に「より安価な」条件を書くことをお勧めします。
  • 文字列を比較する場合は!=を使用する方が直感的ですが、数値を比較する場合は<>がより適切です。
  • ON式は括弧で囲む必要はありません。
  • SELECTの$latは、セキュリティを確保するために、floatとして型キャストする必要があります。
  • 任意のテーブルエイリアスを使用する場合は、aから始めて、壊れた順序を使用するのではなく、そこから降りてください。
  • ASCはデフォルトのソート方向なので、削除できます。

私は盲目的にあなたの数学を信頼するつもりです。サンプルデータがなく、目的の出力がわからなければ、JOINの選択の正しさを完全に確信することはできないので、それらの側面はそのままにしておきます。

新しいRAW SQL:

SELECT *, (ACOS(SIN($lat * PI() / 180) * SIN(latitude * PI() / 180) + COS(78 * PI() / 180) * COS(latitude * PI() / 180) * COS((87 - longitude) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 AS distance
FROM #__content a
RIGHT JOIN #__jreviews_content b ON b.contentid = a.id
LEFT JOIN #__categories c ON a.catid = c.id
LEFT JOIN #__jreviews_media d ON d.listing_id = a.id
WHERE d.main_media = 1
  AND d.media_type = 'photo'
  AND c.title != 'Archives'
  AND b.jr_latitude <> 0.0000000
  AND c.title REGEXP 'Stores|Dining|Events'
HAVING distance <= 50  
ORDER BY distance

HAVINGロジックが実装されている場合、distance列のエイリアスはまだ使用できないため、ここではWHEREが必要です。

PHP/Joomlaの同等(テストされていない):

$query = $db->getQuery(true)
    ->select([
        "*",
        "(ACOS(SIN(" . (float)$lat . " * PI() / 180) * SIN(latitude * PI() / 180) + COS(78 * PI() / 180) * COS(latitude * PI() / 180) * COS((87 - longitude) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 AS distance"
    ])
    ->from("#__content a")
    ->rightJoin("#__jreviews_content b ON b.contentid = a.id")
    ->leftJoin("#__categories c ON a.catid = c.id")
    ->leftJoin("#__jreviews_media d ON d.listing_id = a.id")
    ->where([
        "d.main_media = 1",
        "d.media_type = " . $db->q("photo"),
        "c.title != " . $db->q("Archives"),
        "b.jr_latitude <> 0.0000000",
        "c.title REGEXP " . $db->q("Stores|Dining|Events")
    ])
    ->having("distance <= 50")
    ->order("distance");
0
mickmackusa