即使数据库中的记录满足SELECT语句的条件,MySQL也会返回NULL

时间:2013-04-06 10:13:59

标签: php mysql sql coordinates great-circle

我的数据库有坐标条目。我想获取包含指定半径圆的坐标的条目。因此,我使用spherical law of cosines。 但是在所有数据库条目上检查这样的条件成本太高。 因此,我首先获取位于边界框中的坐标(此框包含上面指定的圆),然后对它们应用spherical law of cosines

但问题是即使我有满足条件的条目,MySQL也会返回NULL。 我分别检查了上述2个条件并且知道spherical law of cosines有效,但是在使用其他条件(边界框)时会出现问题。

link包含我用于这两种情况的代码。

以下是我的代码:

        $R = 3959;  // earth's mean radius in mile

        // first-cut bounding box (in degrees)
        $from_Lat = $userTrip->fromLat;  // latitude of centre of bounding circle in degrees
        $from_Lon = $userTrip->fromLon;  // longitude of centre of bounding circle in degrees
        $from_Rad = $userTripLength * 0.25;  // radius of bounding circle in kilometers

        $from_MaxLat = $from_Lat + rad2deg($from_Rad/$R);
        $from_MinLat = $from_Lat - rad2deg($from_Rad/$R);
        // compensate for degrees longitude getting smaller with increasing latitude
        $from_MaxLon = $from_Lon + rad2deg($from_Rad/$R/cos(deg2rad($from_Lat)));
        $from_MinLon = $from_Lon - rad2deg($from_Rad/$R/cos(deg2rad($from_Lat)));


        $to_Lat = $userTrip->toLat;  // latitude of centre of bounding circle in degrees
        $to_Lon = $userTrip->toLon;  // longitude of centre of bounding circle in degrees
        $to_Rad = $userTripLength * 0.50;  // radius of bounding circle in kilometers

        $to_MaxLat = $to_Lat + rad2deg($to_Rad/$R);
        $to_MinLat = $to_Lat - rad2deg($to_Rad/$R);
        // compensate for degrees longitude getting smaller with increasing latitude
        $to_MaxLon = $to_Lon + rad2deg($to_Rad/$R/cos(deg2rad($to_Lat)));
        $to_MinLon = $to_Lon - rad2deg($to_Rad/$R/cos(deg2rad($to_Lat)));


        $sql = "Select userTrip.id, userTrip.fromLat, userTrip.fromLon, userTrip.toLat, userTrip.toLon,
        acos(sin(:from_lat)*sin(radians(userTrip.fromLat)) + cos(:from_lat)*cos(radians(userTrip.fromLat))*cos(radians(userTrip.fromLon) - :from_lon)) * :R AS SourceDistance,
        acos(sin(:to_lat)*sin(radians(userTrip.toLat)) + cos(:to_lat)*cos(radians(userTrip.toLat))*cos(radians(userTrip.toLon) - :to_lon)) * :R AS DestinationDistance
        From (
            Select userTrip.id, userTrip.fromLat, userTrip.fromLon, userTrip.toLat, userTrip.toLon,
                From userTrip
                    Where userTrip.userId != $this->userId
                    AND userTrip.departureTime > '".date('Y-m-d H:i:s')."'
                    AND userTrip.fromLat Between :from_minLat And :from_maxLat
                    AND userTrip.fromLon Between :from_minLon And :from_maxLon
                    AND userTrip.toLat Between :to_minLat And :to_maxLat
                    AND userTrip.toLon Between :to_minLon And :to_maxLon
            )
          Where acos(sin(:from_lat)*sin(radians(userTrip.fromLat)) + cos(:from_lat)*cos(radians(userTrip.fromLat))*cos(radians(userTrip.fromLon) - :from_lon)) * :R < :from_rad
          AND acos(sin(:to_lat)*sin(radians(userTrip.toLat)) + cos(:to_lat)*cos(radians(userTrip.toLat))*cos(radians(userTrip.toLon) - :to_lon)) * :R < :to_rad";

        $params = array(
        'from_lat'    => $from_Lat, 
        'from_lon'    => $from_Lon,
        'from_minLat' => $from_MinLat, 
        'from_minLon' => $from_MinLon, 
        'from_maxLat' => $from_MaxLat, 
        'from_maxLon' => $from_MaxLon, 
        'from_rad'    => $from_Rad,
        'to_lat'    => $to_Lat, 
        'to_lon'    => $to_Lon, 
        'to_minLat' => $to_MinLat, 
        'to_minLon' => $to_MinLon, 
        'to_maxLat' => $to_MaxLat, 
        'to_maxLon' => $to_MaxLon, 
        'to_rad'    => $to_Rad,
        'R'      => $R
      );

       $stmt = $this->dbLink->prepare($sql);
       try
        {
            $stmt->execute($params);
            $matchCandidates = $stmt->fetchAll();
        }
        catch (PDOException $err)
        {
            echo $err->getMessage();
        }

        if ($matchCandidates == null)
            throw new ErrorException("No match candidates found!");

这始终显示错误“找不到匹配的候选人!”。 在$ params数组中,我最初将纬度和经度转换为弧度(即使不起作用),但经过大量调试后我相信它们应该是度数。

提前谢谢。

2 个答案:

答案 0 :(得分:0)

$myUserId = $this->userId

Select ...
Where userTrip.userId != $myUserId

您可以直接在查询中$this->userId而无需转义它。

答案 1 :(得分:0)

我发现了错误,下面是正确的查询。

$sql = "Select id,fromLat,fromLon,toLat,toLon,
    acos(sin(:from_lat)*sin(radians(fromLat)) + cos(:from_lat)*cos(radians(fromLat))*cos(radians(fromLon) - :from_lon)) * :R AS SourceDistance,
    acos(sin(:to_lat)*sin(radians(toLat)) + cos(:to_lat)*cos(radians(toLat))*cos(radians(toLon) - :to_lon)) * :R AS DestinationDistance
    From (
        Select userTrip.id, userTrip.fromLat, userTrip.fromLon, userTrip.toLat, userTrip.toLon,
            From userTrip
                Where userTrip.userId != $this->userId
                AND userTrip.departureTime > '".date('Y-m-d H:i:s')."'
                AND userTrip.fromLat Between :from_minLat And :from_maxLat
                AND userTrip.fromLon Between :from_minLon And :from_maxLon
                AND userTrip.toLat Between :to_minLat And :to_maxLat
                AND userTrip.toLon Between :to_minLon And :to_maxLon
        ) AS InitialResult
      Where acos(sin(:from_lat)*sin(radians(fromLat)) + cos(:from_lat)*cos(radians(fromLat))*cos(radians(fromLon) - :from_lon)) * :R < :from_rad
      AND acos(sin(:to_lat)*sin(radians(toLat)) + cos(:to_lat)*cos(radians(toLat))*cos(radians(toLon) - :to_lon)) * :R < :to_rad";

1)我必须为内部SELECT查询的结果提供别名。在这种情况下Initialresult 2)我不能在外部SELECT中使用userTrip.因为它在InitialResult而不是userTrip上执行。

相关问题