php - 用于获取地理位置记录的 MySQL 查询优化

标签 php mysql performance pdo query-optimization

我有一个地点的地理位置,这意味着我有一个中心纬度中心经度以及一个半径。在这个半径内有很多具有不同类型的RegionType的区域记录。我想通过匹配该半径内每个RegionType的记录强度来获取正确的RegionType记录。

我当前的逻辑是这样的,

第 1 步:查找最小和最大纬度和经度值

    $milesToKM = 112.654;

    $minLat = $data['lat'] - ($data['rad'] / $milesToKM);

    $maxLat = $data['lat'] + ($data['rad'] / $milesToKM);

    $minLong = $data['lon'] - ($data['rad'] / $milesToKM);

    $maxLong = $data['lon'] + ($data['rad'] / $milesToKM);

Step 2 : Select Regiontype with count

$query = $pdo->prepare("SELECT `RegionType`, count(`RegionType`) as count from (SELECT RegionType FROM data_api_region WHERE (CenterLatitude between $minLat and $maxLat) AND (CenterLongitude between $minLong and $maxLong) AND languageCode = '" . $data['locale'] . "') q GROUP BY `RegionType`");
$query->execute();
$regionCounts = $query->fetchAll(PDO::FETCH_ASSOC);
unset($query);

$finalCountArr = array();
foreach ($regionCounts as $regionCountData) {
$finalCountArr[$regionCountData['RegionType']] = $regionCountData['count'];
}

第3步:决定相关RegionType

switch (true) {
            case (isset($finalCountArr['Continent']) && $finalCountArr['Continent'] > 5):
                $regionTypeFinal = 'Continent';
                break;
            case (isset($finalCountArr['Country']) && $finalCountArr['Country'] > 5):
                $regionTypeFinal = 'Country';
                break;
            case (isset($finalCountArr['Multi-Region (within a country)']) && $finalCountArr['Multi-Region (within a country)'] > 5):
                $regionTypeFinal = 'Multi-Region (within a country)';
                break;
            case (isset($finalCountArr['Province (State)']) && $finalCountArr['Province (State)'] > 5):
                $regionTypeFinal = 'Province (State)';
                break;
            case (isset($finalCountArr['Multi-City (Vicinity)']) && $finalCountArr['Multi-City (Vicinity)'] > 5):
                $regionTypeFinal = 'Multi-City (Vicinity)';
                break;
            case (isset($finalCountArr['City']) && $finalCountArr['City'] > 5):
                $regionTypeFinal = 'City';
                break;
            case (isset($finalCountArr['Neighborhood']) && $finalCountArr['Neighborhood'] > 5):
                $regionTypeFinal = 'Neighborhood';
                break;
            default:
                $regionTypeFinal = 'Point of Interest';
                break;
        }

第4步:获取正确的记录

$query = $pdo->prepare("SELECT `id` as regionId, `RegionName` as regionName,`RegionNameLong` as regionNameLong, `RegionType` as regionType,`CenterLongitude` as centerLongitude, `CenterLatitude` as centerLatitude ,`LanguageCode` as languageCode FROM data_api_region WHERE (CenterLatitude between $minLat and $maxLat) AND (CenterLongitude between $minLong and $maxLong) AND languageCode = '" . $data['locale'] . "' AND RegionType = '$regionTypeFinal'");
        $query->execute();
        $finalResultRegions = $query->fetchAll(PDO::FETCH_ASSOC);

谁能告诉我如何优化这个过程,因为表中缺少记录,所以这个过程需要时间..是否可以通过一个 SQL 查询来实现?

最佳答案

没有测试数据或表布局,所以我无法真正测试它,但它可能可以在单个 SQL 中完成,如下所示:-

SELECT `id` as regionId, `RegionName` as regionName,`RegionNameLong` as regionNameLong, `RegionType` as regionType,`CenterLongitude` as centerLongitude, `CenterLatitude` as centerLatitude ,`LanguageCode` as languageCode 
FROM data_api_region 
INNER JOIN
(
    SELECT CASE
            WHEN RegionType = 'Continent' AND `count` > 5
                THEN 'Continent'
            WHEN RegionType = 'Country' AND `count`  > 5
                THEN 'Country'
            WHEN RegionType = 'Multi-Region (within a country)' AND `count`  > 5
                THEN 'Multi-Region (within a country)'
            WHEN RegionType = 'Province (State)' AND `count`  > 5
                THEN 'Province (State)'
            WHEN RegionType = 'Multi-City (Vicinity)' AND `count`  > 5
                THEN 'Multi-City (Vicinity)'
            WHEN RegionType = 'City' AND `count`  > 5
                THEN 'City'
            WHEN RegionType = 'Neighborhood' AND `count`  > 5
                THEN 'Neighborhood'
            ELSE 'Point of Interest'
        END AS regionTypeFinal
    FROM 
    (
        SELECT `RegionType`, count(`RegionType`) as `count` 
        FROM data_api_region 
        WHERE (CenterLatitude between $minLat and $maxLat) 
        AND (CenterLongitude between $minLong and $maxLong) AND languageCode = '" . $data['locale'] . "'
        GROUP BY `RegionType`
    ) q 
) Sub1
ON data_api_region.RegionType = Sub1.regionTypeFinal
WHERE (CenterLatitude between $minLat and $maxLat) 
AND (CenterLongitude between $minLong and $maxLong) 
AND languageCode = '" . $data['locale'] . "' 

关于php - 用于获取地理位置记录的 MySQL 查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20470281/

相关文章:

php - 删除所有超过 5 天的行

mysql在单个表中的行之间返回TIMEDIFF

sql - 当要跳过的数字很大时, Entity Framework 的“跳过/获取”非常慢

php - 将值计算从 SQL 移到 PHP 层是否更好?

Java - 内联代码会有好处吗?

php - 将复选框值保存到数据库中

javascript - 无法与使用 jquery 的 jquery 加载按钮进行交互

php根据其他数组的顺序重新排序数组

mysql默认值

mysql - 如何使用子查询mysql获取学生列表中的兴趣爱好