我發現堆棧這個問題 - Measuring the distance between two coordinates in PHP朗/緯度距離查詢整個數據庫
答案似乎是完美的,我在很多方面,但我有一個問題。我正在設計一個客戶關係管理系統,並希望有一個郵政編碼半徑搜索選項。我的問題是如何通過可能是1,000條記錄的查詢並在HTML中顯示結果?
我發現堆棧這個問題 - Measuring the distance between two coordinates in PHP朗/緯度距離查詢整個數據庫
答案似乎是完美的,我在很多方面,但我有一個問題。我正在設計一個客戶關係管理系統,並希望有一個郵政編碼半徑搜索選項。我的問題是如何通過可能是1,000條記錄的查詢並在HTML中顯示結果?
因此,我通過結合幾個來源找到的解決方案是(3959英里是6371公里)。我已經在下面包含了一個PHP文件和一個HTML表格,以防止其他人解決這個問題。
開始與您可以讓你從這裏需要的數據:
https://www.freemaptools.com/download-uk-postcode-lat-lng.htm
我會建議使用該網站創建一個基本的MySQL表並導入數據,但是要注意這需要一點點而!無論是在我運行一個查詢來刪除所有空格以便AA11 1AA變成AA111AA之前或之後,這將使表單驗證變得更加簡單。
此迷你漫步使用該鏈接中的數據和表格構造。
首先,你需要的用戶輸入形式,將是這個樣子:
<form action="" method="POST">
<table>
<tr>
<td>Distance:</td>
<td><input type="number" id="distance" name="distance" required></td>
</tr>
<tr>
<td>Miles:<br>Kilometres:</td>
<td><input type="radio" id="unit" name="unit" value="3959" checked><br><input type="radio" id="unit" name="unit" value="6371"></td>
</tr>
<tr>
<td>Postcode:</td>
<td><input type="text" id="postcode" name="postcode" required></td>
</tr>
<tr>
<td></td>
<td><input type="submit" id="submit" name="submit" value="Submit"></td>
</tr>
</table>
</form>
這種形式在你的PHP文件,其中這個坐在你將需要包括此提交到同一頁面,以便代碼郵政編碼轉換爲經度/緯度值:
<?php include 'credentials.php';
$distance = $_POST['distance'];
$unit = $_POST['unit'];
$postcode = str_replace(' ','',$_POST['postcode']);
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT latitude, longitude FROM postcodelatlng WHERE postcode LIKE '$postcode'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$latitude = $row['latitude'];
$longitude = $row['longitude'];
}
} else {
echo "Postcode not found";
}
$conn->close();
?>
確保您有一個credentials.php文件爲這項工作提供數據庫的連接細節。
然後在這個PHP腳本的正下方,我們將放置第二個將返回一定範圍內的所有郵編。然後,您可以調整此腳本以滿足您的需求。我將親自將這個腳本傳遞給另一個更小的表格,以檢查CRM中是否有任何記錄位於特定半徑範圍內,但現在和爲了演示目的而保持簡單!
<?php
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT *,
($unit * acos(cos(radians($latitude)) * cos(radians(latitude)) * cos(radians(longitude) - radians($longitude)) + sin(radians($latitude)) * sin(radians(latitude))))
as distance
FROM postcodelatlng
HAVING distance < $distance";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "" . $row['postcode']. "<br>";
}
} else {
echo "<br>0 results";
}
$conn->close();
?>
主要歸功於這個帖子裏面,這是從使用:
你會得到什麼樣的執行時間?
我做我自己的車輛跟蹤和我的數據庫使用的點列來存儲每個記錄的緯度/經度作爲空間數據,與該列上的空間索引一起。
我目前有13000套保存在數據庫中的座標和給另一組座標下面查詢編輯 我回到我的最接近50隨着每個距離0.009s
SELECT *, (GLength(LineString(location, GeomFromText('POINT(55.0177 -3.0968)'))))
AS distance
FROM blackbox
ORDER BY distance ASC
LIMIT 50
只是嘗試了你的查詢,並增加了按距離排序,它花了0.024s,將你的HAVING distance < x
添加到我的查詢中讓我降到0。008s
聽起來就像我們相當匹配然後!我急於補充這並不是我所有的工作,它是我自己調整來源的組合,可以幫助任何有我同樣問題的人。我認爲整個解決方案的主要優點是將郵政編碼轉換爲長/經。我會稍後嘗試運行您的查詢,看看我得到了什麼。 – Rockhopper
這不是一個簡單的問題 - 但如果你不使用半徑,只需創建一個邊長爲2r的正方形,並且在中間的郵政編碼,就可以計算long/lat的上限和下限然後找到落在長/長邊界之間的記錄 - 它仍然是一個昂貴的查詢。根據您使用的特定DB,您可以優化。 –
查看[MySQL Spatial Extensions](https://dev.mysql.com/doc/refman/5.6/en/spatial-extensions.html),但請記住MySQL不是這種類型的理想數據庫工作。在實踐中,Postgres + [PostGIS](http://www.postgis.net)通常要好得多。 – tadman
謝謝你們都非常感謝你的幫助。我發現了一個查詢,我會在上面發帖,在2秒鐘內完成,這對我們來說很好,但我理解對其他人不理想。 – Rockhopper