Laravel Query Builder - используйте выбранное значение в предложении WHERE без повторения кода - PullRequest
0 голосов
/ 26 октября 2019

Я пытаюсь преобразовать запрос RAW SQL в конструктор запросов Laravel, однако я не знаю, как использовать производное значение в операторе выбора в предложении WHERE. Делая это в RAW SQL, я делаю это, вкладывая запрос select.

Рабочий запрос RAW

$query = DB::select("
        SELECT *
        FROM
          (SELECT DISTINCT a.postcode, b.id, b.name, d.product, e.distance product_distance,
                ROUND((SELECT 6371  * acos( cos( radians( $lat ) ) * cos( radians( a.latitude ) )
                                                         * cos( radians( $lng ) - radians(a.longitude) )
                                                         + sin( radians( $lat ) ) * sin( radians( a.latitude ) ) ) ),0) AS point_distance
                FROM postcodes_geo AS a
                JOIN businesses As b
                    ON b.postcode = a.postcode
                JOIN business_services As c
                    ON b.id = c.business_id
                JOIN business_subscriptions As d
                    ON b.id = d.business_id
                JOIN ref_business_products AS e
                    ON d.product = e.product
                WHERE b.deleted_at IS NULL
                AND c.service = '$service'
                AND c.deleted_at IS NULL) t
                WHERE t.point_distance <= t.product_distance
          ORDER BY point_distance
          ");

RAW SQL nested query

Текущий запросзапрос строителя

$query = DB::table('postcodes_geo')
            ->join('businesses', 'postcodes_geo.postcode', '=', 'businesses.postcode')
            ->join('business_services', 'businesses.id', '=', 'business_services.business_id')
            ->join('business_subscriptions', 'businesses.id', '=', 'business_subscriptions.business_id')
            ->join('ref_business_products', 'business_subscriptions.product', '=', 'ref_business_products.product')
            ->select(DB::raw("DISTINCT postcodes_geo.postcode, businesses.id, businesses.name, business_subscriptions.product, ref_business_products.distance,
                            ROUND((SELECT 6371  * acos( cos( radians( $lat ) ) * cos( radians( postcodes_geo.latitude ) )
                                                         * cos( radians( $lng ) - radians(postcodes_geo.longitude) )
                                                         + sin( radians( $lat ) ) * sin( radians( postcodes_geo.latitude ) ) ) ),0) AS point_distance"))
            ->whereNull('businesses.deleted_at')
            ->whereNull('business_services.deleted_at')
            ->when($services, function ($query, $services) {
                return $query->whereIn('business_services.service', explode(',', $services));
            })
            ->where(DB::raw("ROUND((SELECT 6371  * acos( cos( radians( $lat ) ) * cos( radians( postcodes_geo.latitude ) )
                                                         * cos( radians( $lng ) - radians(postcodes_geo.longitude) )
                                                         + sin( radians( $lat ) ) * sin( radians( postcodes_geo.latitude ) ) ) ),0)"), "<=", 'ref_business_products.distance')
            ->get();

Как видите, я не хочу повторять ту же часть запроса (хотя он работает). SQL query builder laravel

1 Ответ

0 голосов
/ 26 октября 2019

Вы можете воспользоваться перегруженным предложением MySQL HAVING, которое позволит вам ссылаться на псевдоним point_distance, определенный в предложении select:

$query = DB::table('postcodes_geo')
    ...
    ->having(DB::raw('point_distance <= ref_business_products.distance'))
    ->get();

Примечание. Если вы используете версиюMySQL ранее, чем 5.7.5, тогда вам нужно было бы отключить режим ONLY_FULL_GROUP_BY, чтобы использовать перегруженный HAVING, как это делается в моем ответе.

...