Mysql 当在PhpMyAdmin中运行时,在何处给我不同的结果

Mysql 当在PhpMyAdmin中运行时,在何处给我不同的结果,mysql,laravel,Mysql,Laravel,当我在phpMyAdmin中运行以下查询时 SELECT locations.name, locations.id, locations.lon, locations.lat, locations_categories.category_id as catId, locations_categories.location_id as locId, haversine(40,9

当我在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
它给出了以下正确的结果

但是,当我在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));
下面是截图


我的问题是,为什么这可以工作并返回PhpMyAdmin中所需的所有值,但在应用程序中运行时却不能?

在这里使用Laravel代码,而不是单个原始查询。这允许您利用
WHERE
函数,该函数可以将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();

您的问题的答案与如何实现绑定变量以及类型强制有关

绑定的
将替换为单个值。这不是简单的SQL语句搜索和替换。因此,在(?)中的
位置\u categories.category\u id中,
的值实际上是整个值
9”、“1”、“7
。但是,为什么它仍然返回
locations\u categories.category\u id=9的结果呢

因为类型强制。我假设
locations\u categories.category\u 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)

原始查询必须如下所示,并传递一个参数数组以绑定到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);

很简单:
“9”、“1”、“7”
是三个不同的值,而
“9”、“1”、“7”
被视为单个字符串,并在其周围附加引号。@LukaszSzozda我也注意到了这一点,我认为这是问题所在,但当它仍然搜索9时,我感到困惑。你知道如何解决这个问题吗?Laravel有一个
函数,其中
函数接受一个PHP值数组。但是,似乎没有任何方法可以按照您想要的方式直接绑定PHP数组。有一些选择。非常感谢!我将用正确的工作代码对您的答案进行一些编辑,然后我将接受您的答案!
$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);