将一个查询与PHP

时间:2015-05-24 22:28:59

标签: php sql combinations

我有两个文字输入。像这样:

enter image description here

所以,我有一些动态的ajax搜索。我传递输入数据并做两个不同的mysql选择。像这样:

  

表格终结图 - 选择1

id -------- latitud-----longitud---

1        |  6.2523915 | -75.5737028 |
2        |  6.2640349 | -75.5990783 |
3        |  6.2642411 | -75.5999791 |
4        |  6.2638461 | -75.5982590 |
-------------------------------------
  

表finalmap - SELECT 2

id -------- latitud-----longitud---

6        |  6.262669 | -75.596799 |
7        |  6.258019 | -75.598001 |
8        |  6.253668 | -75.599374 |
9        |  6.250724 | -75.602335 |
-------------------------------------

所以,我想比较每一个"纬度和纵向"与所有"纬度"和"纵向" SELECT2的字段:

enter image description here

我有这个Php,我必须做一些改进,但可以说它有效:

<?php
$buscar = $_POST['b'];
$buscarcarrera = $_POST['c'];
$whatIWant = substr($buscar, strpos($buscar, "Calle") + 5);
$whatIWant2 = substr($buscarcarrera, strpos($buscarcarrera, "Carrera") + 5);
$vacio = "Calle50A";
$vacioc = "Carrera50A";

if (preg_match('/[A-Za-z]/', $whatIWant))
    {
    buscar($buscar, "", $buscarcarrera, "");
    }
  else
    {
    buscar($buscar, $vacio, $buscarcarrera, $vacioc);
    }

function buscar($b, $exclusion, $buscarcarrera, $exclusion2)
    {
    $con = mysql_connect('localhost', 'root', '');
    mysql_select_db('map', $con);
    $sql = mysql_query("SELECT * FROM finalmap WHERE calle LIKE '%" . $b . "%' AND calle not in ('$exclusion')", $con);
    $contar = mysql_num_rows($sql);
    if ($contar == 0)
        {
        echo "No se han encontrado resultados para '<b>" . $b . "</b>'.";
        }
      else
        {
        while ($row = mysql_fetch_array($sql))
            {
            $nombre = $row['calle'];
            $id = $row['id'];
            $lat = $row['latitud'];
            $lon = $row['longitud'];
            }
        }

    $sql2 = mysql_query("SELECT * FROM finalmap WHERE calle LIKE '%" . $buscarcarrera . "%' AND calle not in ('$exclusion2')", $con);
    $contar2 = mysql_num_rows($sql2);
    if ($contar2 == 0)
        {
        echo "No se han encontrado resultados para '<b>" . $b . "</b>'.";
        }
      else
        {
        while ($row2 = mysql_fetch_array($sql2))
            {
            $nombre2 = $row2['calle'];
            $id2 = $row2['id'];
            $lat2 = $row2['latitud'];
            $lon2 = $row2['longitud'];
            }
        }
    }

function distance($lat1, $lon1, $lat2, $lon2, $unit)
    {
    $theta = $lon1 - $lon2;
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
    $dist = acos($dist);
    $dist = rad2deg($dist);
    $miles = $dist * 60 * 1.1515;
    $unit = strtoupper($unit);
    if ($unit == "K")
        {
        return ($miles * 1.609344);
        }
      else
    if ($unit == "N")
        {
        return ($miles * 0.8684);
        }
      else
        {
        return $miles;
        }
    }

echo distance(32.9697, -96.80322, 29.46786, -98.53506, "M") . " Miles<br />";
echo distance(32.9697, -96.80322, 29.46786, -98.53506, "K") . " Kilometers<br />";
echo distance(32.9697, -96.80322, 29.46786, -98.53506, "N") . " Nautical Miles<br />";
?>

然后:如何使用函数比较每个值来确定坐标之间的接近度(使用我的distance()函数)? 我的问题是我不知道如何比较第一个查询的每个点与第二个查询的每个点之间的距离,以及每种可能的组合。

我想要比较这个函数比较(lat1,lon1,lat2,lon2); (lat1,lon1,lat3,lon3),(lat1,lon1,lat4,lon4),(lat1,lon1,lat5,lon5),(lat1,lon1,lat6,lon6)等等。

非常感谢您提供任何帮助

9 个答案:

答案 0 :(得分:7)

你的逻辑是完全错误的,你正在使你正在寻找的东西变得复杂。它比你想象的要简单得多。

首先:为了大幅加快脚本和查询并防止任何攻击,请使用PDO预处理语句和安全协议。 Mysql没有准备好的语句已被弃用超过十年!!!

我的经验(25年的编码)让我永远不会相信你的服务器会发生什么,所以我对安全有点恐惧...... 本教程将介绍您需要执行的第一个基本步骤,并按原样解释此脚本(按原样复制所有代码)。

注意,使用本地IP地址而不是Localhost将使mysql连接速度提高2到5,具体取决于开发平台(灯,wamp等...)

设置执行参数

ini_set('memory_limit', '64M'); // memory limit used by script
set_time_limit(0);              // no time limit

建立您的安全mysql连接

try {
    $con = new PDO('mysql:host=127.0.0.1;dbname=map;charset=UTF8','root','password');
    $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

建立二级安全协议以检查它是否真的是一个ajax调用

$isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND
    strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
if (!$isAjax) {
    $user_error = 'Access denied - not an AJAX request from allowed computer...';
    trigger_error($user_error, E_USER_ERROR);
    exit;
}

第二:使用距离函数 INSIDE 您的mysql查询,以便正确排序您要查找的结果。请注意,此处使用的mysql距离与您当前使用的距离不同(更快,更精确)。 它将为您提供表1中参考点与表2中所有其他参考点之间的距离(以km为单位),按距离排序(最接近第一行)。

我们假设您从这样的ajax获得结果:

if($isAjax){
    $param4 = '%' . $_POST['b']. '%';  // MYSQL LIKE bind param buscar 
    $param5 = '(' . $_POST['c'] . ')'; //MYSQL NOT IN bind param  buscarcarrera
}

我们假设您从第一个查询中获得结果(简化):

$sql1_array = array(
    array('id' => 1, 'Lati' => 6.2523915, 'Longi' => -75.5737028),
    array('id' => 2, 'Lati' => 6.2640349, 'Longi' => -75.5990783)
);

(注意:总是使用&#34; lati&#34;和#34; longi&#34;以避免与PHP函数冲突,例如&#34; long&#34;)

您准备好的陈述:

$sql2 = "SELECT *, ( 6371 * acos( cos(radians(?)) 
* cos(radians(Latitude)) * cos(radians(Longitude) - radians(?)) + 
sin( radians(?) ) * sin(radians(Latitude))))  AS distance 
FROM finalmap WHERE calle LIKE ? AND calle NOT IN ? 
ORDER BY distance LIMIT 10";

$stmt = $con->prepare($sql2);

第三次:使用每个query1结果执行循环以获得与表2相比的距离。在循环中,将参数绑定到准备好的stmt。这将大大加快您的查询速度,因为与数据库的连接是持久的,并且使用PDO(已编译和在内存中)准备查询。

foreach ($sql1_array as $key => $value) {
    $stmt->bindParam(1, $value['Lati'], PDO::PARAM_INT);
    $stmt->bindParam(2, $value['Longi'], PDO::PARAM_INT);
    $stmt->bindParam(3, $value['Lati'], PDO::PARAM_INT);
    $stmt->bindParam(4, $param4, PDO::PARAM_STR);
    $stmt->bindParam(5, $param5, PDO::PARAM_STR);
    $stmt->execute();
    $count = $stmt->rowCount();
    if ($count >= 1) {
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
      }
}


/*    $result ordered by distance     */

|**************************************|
|field 0 | field 1 | field 2 | distance|
|**************************************|
| 1      | a1      | a2      | 0.00123 | 1 meters
| 2      | b1      | b2      | 0.01202 | 12 meters
| 3      | c1      | c2      | 0.23453 | 234 meters
| 4      | d1      | d2      | 1.58741 | 1km and 587 meters
|**************************************|  

我想你们都已经准备好了!享受。

答案 1 :(得分:2)

你应该这样做:

function buscar($b, $exclusion, $buscarcarrera, $exclusion2)
{
    $nombre1 = array();
    $id1= array();
    $lat1= array();
    $lon1= array();
    $nombre2 = array();
    $id2= array();
    $lat2= array();
    $lon2= array();

    $con = mysql_connect('localhost', 'root', '');
    mysql_select_db('map', $con);
    $sql = mysql_query("SELECT * FROM finalmap WHERE calle LIKE '%" . $b . "%' AND calle not in ('$exclusion')", $con);
    $contar = mysql_num_rows($sql);
    if ($contar == 0)
    {
        echo "No se han encontrado resultados para '<b>" . $b . "</b>'.";
        } else {
    while ($row = mysql_fetch_array($sql))
        {
            if(array_key_exists('calle',$row) && array_key_exists('id',$row) && array_key_exists('latitud',$row) &&  array_key_exists('longitud',$row)) {
                // ignore data with a missing field
                $nombre1[] = $row['calle'];
                $id1[] = $row['id'];
                $lat1[] = $row['latitud'];
                $lon1[] = $row['longitud'];
            }
        }
    }

    $sql2 = mysql_query("SELECT * FROM finalmap WHERE calle LIKE '%" . $buscarcarrera . "%' AND calle not in ('$exclusion2')", $con);
    $contar2 = mysql_num_rows($sql2);
    if ($contar2 == 0)
    {
        echo "No se han encontrado resultados para '<b>" . $b . "</b>'.";
    } else {
        while ($row2 = mysql_fetch_array($sql2))
        {
            if(array_key_exists('calle',$row2) && array_key_exists('id',$row2) && array_key_exists('latitud',$row2) &&  array_key_exists('longitud',$row2)) {
                // ignore data with a missing field
                $nombre2[] = $row2['calle'];
                $id2[] = $row2['id'];
                $lat2[] = $row2['latitud'];
                $lon2[] = $row2['longitud'];
            }
        }
    }
    $nbData1 = count($nombre1);
    $nbData2 = count($nombre2);
    if($nbData1 > 0 && $nbData2 > 0) {
        // there are data in both 1st and 2nd query
        $distances = array();
        // loop on all data from 1st query
        for($i1 = 0; $i1 < $nbData1; $i1++) { 
            // loop on all data from 2nd query
            for($i2 = $i1; $i2 < $nbData2; $i2++) {
                // storing result of the distance
                $distances[] = array('i1' => $i1, 
                                    'i2' => $i2, 
                                    'dist' => array('M' => distance($lat1[$i1], $lon1[$i1], $lat2[$i2], $lon2[$i2], 'M'),
                                                    'K' => distance($lat1[$i1], $lon1[$i1], $lat2[$i2], $lon2[$i2], 'K'),
                                                    'N' => distance($lat1[$i1], $lon1[$i1], $lat2[$i2], $lon2[$i2], 'N')
                                              )
                               )
            }
        }
    }

    foreach($distances as $distance) {
        // use each result
        $i1 = $distance['i1'];
        $lat1 = $distance['lat1'];
        $lon1 = $distance['lon1'];
        $i2 = $distance['i1'];
        $lat2 = $distance['lat2'];
        $lon2 = $distance['lon2'];
        $dist = $distance['dist'];
        $distM = $dist['M'];
        $distK = $dist['K'];
        $distN = $dist['N'];
        echo "Have fun with theses data !\n";
    }
}

所以,存储行的内容 然后解析所有数据,计算所有可能的距离 然后根据需要使用结果。

答案 2 :(得分:1)

在第二个查询中处理距离计算要好得多,而且速度更快,因此不需要distance()函数。你的公式似乎也不正确。

prt.ef$frontier  #see the EF
xylims=apply(prt.ef$frontier[,c(2,1)],2,range)*c(.98,1.01)
chart.EfficientFrontier(prt.ef, match.col="pasd", 
      main="Portfolio Optimization", 
      xlim=xylims[,1], ylim=xylims[,2])
#or
plot(prt.ef$frontier[,c(2,1)],col=2)

答案 3 :(得分:0)

我先试试。

$output_array = array();
$i = 0;

while ($row = mysql_fetch_array($sql))
{
      $j = 0;
      while ($row2 = mysql_fetch_array($sql2))
      {
           $out_array[$i][$j][0] = $row2['latitud'] - $row['latitud']
           $out_array[$i][$j][1] = $row2['longitud'] - $row['longitud']
           ++$j;
      }
      ++$i;
}
print "<pre>";
print_r($out_array);
print "</pre>";

预览(随机数字):

 Array
(
[0] => Array
    (
        [0] => Array
            (
                [0] => 6
                [1] => 9
            )

        [1] => Array
            (
                [0] => 6
                [1] => 9
            )

        [2] => Array
            (
                [0] => 6
                [1] => 9
            )
         ............
         ............
         ............
  

第一个结果纬度之间的数组[0] [0] [0] == 差异(表1) AND 第一个结果纬度(表2)

     

数组[0] [1] [0] == 差异纬度(第1个res表1) AND (第2个res表2)

纵向的情况

答案 4 :(得分:0)

我认为表的cross join将完成你的工作。

假设第一个表是Table1,第二个表是Table2。 所以查询:

Select Table1.id, Table1.latitud, Table1.longitude, 
       Table2.id, Table2.latitud, Table2.longitude 
from
       Table1 , Table2

这将为您提供所需的所有组合。

答案 5 :(得分:0)


我认为INNER JOIN会起作用。我很困惑你会提供table-1 long和lat值。
所以我写了两个选项。
让我们说第一个表是table1,第二是table2

  1. 当您提供表1的{* 2}}
  2. 的纬度和长值时
  3. 它将在表格
    select  Name,Designation ,case when @value = 1 then DOB else DOJ end  
    from    Employee
    where   case when @value = 1 then DOB else DOJ end >='06/01/2015' 
            and case when @value = 1 then DOB else DOJ end < dateadd(dd,1,'06/01/2015')
    
  4. 中提供相等值的过滤结果

    让我知道是否需要其他任何东西。
    感谢你。

答案 6 :(得分:0)

您可以轻松地在SQL中生成必要的结果集,而无需编写大量PHP代码。

如果您实际显示您希望结果看起来像表格,那么这也会使事情变得容易多了。我对你真正要做的事感到困惑。我的假设是,当纬度与 OR 完全匹配时,你想要匹配两个查询。

更新:我发现你的PHP代码中隐藏了SQL。这样的事情应该有效:

"SELECT t1.latitud AS lat1, t1.longitud AS lon1,
    t2.latitud AS lat2, t2.longitud AS lon2
FROM finalmap AS t1
INNER JOIN finalmap AS t2 ON t1.latitud=t2.latitud OR t1.longitud=t2.longitud
WHERE t1.calle LIKE '%" . $b . "%' AND t1.calle not in ('$exclusion')
    AND t2.calle LIKE '%" . $buscarcarrera . "%' AND t2.calle NOT IN ('exclusion2');"

如果您想要SELECT 1中的所有结果,即使SELECT 2中没有匹配项,请将INNER JOIN更改为LEFT JOIN

我还注意到,在返回查询后,您正在检查字段是否包含值。您可以在SQL查询的WHERE子句中执行这些检查,这样您就不会获得任何实际不需要的结果。它只取决于“无值”看起来是什么样的(NULL?空字符串?等),如何检查它。

答案 7 :(得分:0)

您可以使用两个表格的笛卡尔积,以便找到所有可能的组合。
否则,采取两个循环,如

for(int i=0;i < n; i++)
  for(int j=0; j< m; j++)
    someProcess(a[i][0], a[i][1], b[j][0], b[j][1]);

这将为您提供所有可能的组合 然后,您的函数应具有地理编码/反向地理编码的逻辑以计算距离。

我希望这有帮助!!

答案 8 :(得分:0)

我支持this回答,但添加了另一个要点:

第四:不要在PHP和MySQL中使用自定义编码的半正式公式进行距离计算和排序。 MySQL长期以来一直支持空间功能。此外,在处理GIS时,最好转向PostgreSQL + PostGIS扩展

第五:按距离排序时使用MySQL或任何其他RDBMS空间索引。 我怀疑您可以使用“每个距离比较”方法更有效地编码。

解决方案:审核this回答并将以下查询应用于您的数据库表:

ALTER TABLE `finalmap` ENGINE=MYISAM; -- changing your storage engine to MyISAM. It supports spatial indexes in MySQL
ALTER TABLE `finalmap` ADD `pt` POINT NOT NULL; -- adding POINT() spatial datatype for zip cetner. Eventually, you may remove the old lat/lng decimal columns
UPDATE `finalmap` SET `pt` = POINT(latitud,longitud);
ALTER TABLE `finalmap` ADD SPATIAL INDEX(`pt`);

然后,假设您在输入中得到一个坐标(比方说(6.25,-75.6)),您需要与表中的所有记录进行比较并找到最接近的记录,您需要:

SELECT *, ST_Distance_Sphere(`pt`,POINT('6.25','-75.6')) as `dst`
FROM `fnialmap`
ORDER BY `dst`
LIMIT 1;

最后,第六:请用英语命名您的列和变量。可能是因为其他人将来支持你的代码,他们必须处理“纬度”和“纵向”