web-dev-qa-db-fra.com

Joomla 2.5, comment utiliser "HAVING" en utilisant un objet de requête

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

J'ai réussi à écrire la requête avec Query Object sans HAVING

$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);

S'il vous plaît, aidez-moi, s'il vous plaît, à écrire le HAVING dans ce Query Object

2
Siva.G ツ

Si vous utilisez la clause having sans Group_by, il agira exactement comme la clause where.

La classe JDatabaseQuery fournit une méthode pour avoir une clause.

Essaye ça

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

J'aimerais ajouter quelques raffinements à la requête publiée ...

  • Bien que valide, je vous recommande de construire vos filtres conditionnels dans la clause WHERE par opposition à l'expression ON de JOIN - il sera plus simple de lire de cette façon.
  • Plutôt que d’écrire 3 conditions LIKE distinctes, il sera plus bref d’écrire une seule condition REGEXP condensant les 3 sous-chaînes ciblées.
  • Il n'y a aucun avantage à 1 = 1
  • Je recommande d’écrire vos conditions "moins chères" avant les conditions "plus lourdes".
  • Je pense que c'est plus intuitif d'utiliser != lors de la comparaison d’une chaîne, alors que <> est plus approprié lors de la comparaison de valeurs numériques.
  • Les expressions ON n'ont pas besoin d'être entourées de parenthèses.
  • $lat dans SELECT doit être transtypé en tant que float pour de meilleures pratiques de sécurité.
  • Si vous allez utiliser des alias de table arbitraires, vous devriez commencer par a et descendre à partir de là au lieu d'utiliser un ordre cassé.
  • ASC est le sens de tri par défaut, il peut donc être supprimé.

Je vais aveuglément faire confiance à vos calculs et je ne peux pas être tout à fait sûr de la justesse de vos choix de JOIN sans avoir quelques exemples de données et connaître le résultat souhaité. Je laisserai donc ces aspects de côté.

Nouveau 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 est nécessaire ici car l'alias de colonne distance n'est pas encore disponible lorsque la logique WHERE est implémentée.

équivalent PHP/Joomla (non testé):

$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