Где в дают мне разные результаты, когда побежал в phpmyadmin


Где в дают мне разные результаты, когда побежал в phpmyadmin

07.10.2018 05:48:43 Просмотров 40 Источник

Когда я запускаю следующий запрос в phpMyAdmin

    SELECT 
        locations.name,
        locations.id,
        locations.lon,
        locations.lat,
        locations_categories.category_id as catId,
        locations_categories.location_id as locId,
        haversine(40,90,locations.lon,locations.lat) as distance
    FROM locations_categories, locations  
    WHERE locations.id = locations_categories.location_id
    AND locations_categories.category_id IN ("9","1","7")  
    ORDER BY `distance` ASC

Это дает мне следующие результаты, которые являются правильными.

enter image description here

Но когда я запускаю следующее в своем приложении Laravel, оно возвращает только местоположения с catId 9.

        // dump($request->categories);
        $categories = implode('","',$request->categories);

        //dd($categories);


        $statement = <<<'ENDSTATEMENT'
        SELECT 
            locations.name,
            locations.id,
            locations.lon,
            locations.lat,
            locations_categories.category_id as catId,
            locations_categories.location_id as locId,
            haversine(?,?,locations.lon,locations.lat) as distance
        FROM locations_categories, locations  
        WHERE locations.id = locations_categories.location_id
        AND locations_categories.category_id IN (?)  
        ORDER BY `distance` ASC
ENDSTATEMENT;

    $locations = DB::select($statement, array($request->lon, $request->lat, $categories));

Результаты исследования

dd($categories);

это следующий скриншот

enter image description here

Мой вопрос заключается в том, почему это работает и возвращает все значения, необходимые в PhpMyAdmin, но не при запуске в приложении??

У вопроса есть решение - Посмотреть?

Ответы - Где в дают мне разные результаты, когда побежал в phpmyadmin / WHERE IN give me different results when ran in PhpMyAdmin

Является ответом!
Tim Biegeleisen

07.10.2018 06:01:51

Используйте здесь код Laravel, а не один необработанный запрос. Это позволяет вам воспользоваться функцией whereIn, которая может правильно привязать PHP-массив значений к выражению WHERE.

$locations = DB::table('locations_categories as lc')
    ->join('locations', 'locations.id', '=', 'lc.location_id')
    ->whereIn('lc.category_id', $request->categories)
    ->selectRaw('locations.name, locations.id, locations.lon, locations.lat,'
        . 'lc.category_id as catId,'
        . 'lc.location_id as locId,'
        . 'haversine(?, ?, locations.lon,locations.lat) as distance',
    [$request->lon, $request->lat])
->get();
dossy

07.10.2018 06:10:38

Ответ на ваш вопрос связан с тем, как реализуются связанные переменные в сочетании с принудительным типом.

Привязка ? заменяется одним значением. Это не просто поиск и замена в операторе SQL. Итак, в locations_categories.category_id IN (?) значение ?-это буквально все значение 9","1","7. Но почему это все еще возвращает результаты там, где locations_categories.category_id = 9?

Из-за принуждения типа. Я предполагаю, что locations_categories.category_id - это числовой, а не символьный столбец в вашей схеме. Поэтому при выполнении SQL строковое значение в правой части, 9","1","7, принудительно преобразуется в числовое представление, которое оказывается 9. Вы можете увидеть это более явно здесь:

mysql> select cast('9","1","7' as signed);
+-----------------------------+
| cast('9","1","7' as signed) |
+-----------------------------+
|                           9 |
+-----------------------------+
1 row in set, 1 warning (0.05 sec)

mysql> show warnings;
+---------+------+------------------------------------------------+
| Level   | Code | Message                                        |
+---------+------+------------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: '9","1","7' |
+---------+------+------------------------------------------------+
1 row in set (0.04 sec)
adriano machado

18.09.2020 11:45:54

Необработанный запрос должен быть таким и передавать массив параметров для привязки к select:

SELECT 
    locations.name,
    locations.id,
    locations.lon,
    locations.lat,
    locations_categories.category_id as catId,
    locations_categories.location_id as locId,
    haversine(:req_lon, :req_lat, locations.lon, locations.lat) as distance
FROM locations_categories, locations  
WHERE 
    locations.id = locations_categories.location_id AND 
    locations_categories.category_id IN (:cat0, :cat1, :cat2)  
ORDER BY `distance` ASC

Используйте этот код с параметрами для привязки:

$categories = ["9","1","7"]; // example

$bind = [];
foreach($categories as $k => $cat) {
    $bind['cat'.$k] = $cat;
}
$listCat = implode(', ', array_keys($bind));

// add others filters
$bind['req_lon'] = $request->lon;
$bind['req_lat'] = $request->lat;

$sql = 
"   SELECT 
        locations.name,
        locations.id,
        locations.lon,
        locations.lat,
        locations_categories.category_id as catId,
        locations_categories.location_id as locId,
        haversine(:req_lon, :req_lat, locations.lon, locations.lat) as distance
    FROM locations_categories, locations  
    WHERE 
        locations.id = locations_categories.location_id AND 
        locations_categories.category_id IN ({$listCat})  
    ORDER BY `distance` ASC";

$locations = DB::select($sql, $bind);
Помочь в развитии проекта:
Закрыть X