I have MySQL table with some libraries. I need to make SQL query in PHP, which will select library by ID, and count distance. This is invalid query. Where I'm doing mistake in this query ?
$query = "SELECT *,
( 6371 *
acos(
cos(radians(" . $center_lat . ")) *
cos(radians(lat)) *
cos(radians(lng) - radians(" . $center_lng . ")) +
sin(radians(" . $center_lat . ") ) *
sin(radians( lat ) )
)
) AS distance
FROM `libraries`
WHERE id = ". $id ."
LIMIT 0 , 1";
Related
I have a web page where a user clicks on a map, the latitute and longitude are passed to text fields, and along with some other details the data is submitted to the database. I have a formula for calculating the nearest town, and I have a little sample table of towns with their latitudes and logitudes.
At the moment I can display the nearest town and distance, but I can't get it to send to the database. I think I need to put the two queries together but I don't know how. Please be kind, I know my code is terrible and I have lots of security issues which I'm going to try to address later. Thank you!
<?php
$conn = Connect();
/**
* Use the Haversine Formula to display the 100 closest matches to $origLat, $origLon
* Only search the MySQL table $tableName for matches within a 10 mile ($dist) radius.
*/
$origLat = $conn->real_escape_string($_POST['lat']);
$origLon = $conn->real_escape_string($_POST['lng']);
// This is the maximum distance (in miles) away from $origLat, $origLon in which to search
$dist = 50;
$query = "SELECT Townland, lat, lng, 3956 * 2 *
ASIN(SQRT( POWER(SIN(($origLat - lat)*pi()/180/2),2)
+COS($origLat*pi()/180 )*COS(lat*pi()/180)
*POWER(SIN(($origLon-lng)*pi()/180/2),2)))
as distance FROM townland WHERE
lng between ($origLon-$dist/cos(radians($origLat))*69)
and ($origLon+$dist/cos(radians($origLat))*69)
and lat between ($origLat-($dist/69))
and ($origLat+($dist/69))
having distance < $dist ORDER BY distance limit 1";
$result = mysqli_query($conn, $query) or die(mysql_error());
while($row = mysqli_fetch_assoc($result)) {
echo $row['Townland']." > ".$row['distance']."<BR>";
}
$User_ID = $conn->real_escape_string($_POST['User_ID']);
$Species_Name = $conn->real_escape_string($_POST['Species_Name']);
$No_Of_Birds = $conn->real_escape_string($_POST['No_Of_Birds']);
$newdate = $conn->real_escape_string($_POST['Sighting_Date']);
//Converts date to 'yyyy-mm-dd' acceptable to mysql
$newdate=date('Y-m-d',strtotime($newdate));
$Sighting_Details = $conn->real_escape_string($_POST['Sighting_Details']);
$lat = $conn->real_escape_string($_POST['lat']);
$lng = $conn->real_escape_string($_POST['lng']);
$townland = $row['Townland'];
$query = "INSERT into sighting
(User_ID, Species_Name, No_Of_Birds,
Sighting_Date, Sighting_Details,
lat, lng, Townland)
VALUES('" . $User_ID . "','" . $Species_Name . "','" . $No_Of_Birds . "','"
. $newdate . "','" . $Sighting_Details . "','"
. $lat . "','" . $lng . "','" . $townland . "')";
$success = $conn->query($query);
if (!$success) {
die("Couldn't enter data: ".$conn->error);
}
header("Location: ../View/thankYouSubmitSighting.php");
$conn->close();
exit();
while($row = mysqli_fetch_assoc($result)) {
echo $row['Townland']." > ".$row['distance']."<BR>";
}
mysqli_close($conn);
?>
If you need insert the result from query in a table eg: my_table
could be you need an insert select query ( a single sql command composed by two part )
"INSERT into my_table (Townland, lat, lng, distance)
SELECT Townland, lat, lng, 3956 * 2 *
ASIN(SQRT( POWER(SIN(($origLat - lat)*pi()/180/2),2)
+COS($origLat*pi()/180 )*COS(lat*pi()/180)
*POWER(SIN(($origLon-lng)*pi()/180/2),2)))
as distance FROM townland WHERE
lng between ($origLon-$dist/cos(radians($origLat))*69)
and ($origLon+$dist/cos(radians($origLat))*69)
and lat between ($origLat-($dist/69))
and ($origLat+($dist/69))
having distance < $dist ORDER BY distance limit 1";
I'm trying to return results by latitude and longitude in me BD.
I have this script. It works fine when I do the phpmyadmin
SELECT `loc` . * , (
(
(
ACOS( SIN( ( 4.6665578 * PI( ) /180 ) ) * SIN( (
`latitude_advertiser` * PI( ) /180 ) ) + COS( ( 4.6665578 * PI( ) /180 ) ) * COS( (
`latitude_advertiser` * PI( ) /180 )
) * COS( (
(
- 74.0524521 - `longitude_advertiser`
) * PI( ) /180 )
)
)
) *180 / PI( )
) *60 * 1.1515
) AS `distance`
FROM `user_profile_` `loc`
HAVING `distance` <1
LIMIT 0 , 30
However, when I try to do the similar procedure using php my query Returns How Empty.
$connect = mysqli_connect('localhost','root','');
$db = mysqli_select_db($connect, 's2_001') or die ('Erro #1010');
$distance = 10;
$latitude = 4.6665578;
$longitude = -74.0524521;
$sql = "SELECT `loc`.*, (((acos(sin(($latitude*pi()/180)) * sin((`latitude_advertiser`*pi()/180))+cos(($latitude*pi()/180)) * cos((`latitude_advertiser`*pi()/180)) * cos((($longitude - `longitude_advertiser`)*pi()/180))))*180/pi())*60*1.1515) AS `distance` FROM `user_profile_` `loc` HAVING `distance` < 1";
$query = mysqli_query($connect, $sql);
while($row = mysqli_fetch_array($query)){
echo $row['id'] . '-' . $row['distance'] . '<br>';
}
echo mysqli_num_rows($query); // no line here
echo $sql; // test query, working in phpmyadmin
My script is running too slow when searching zipcodes within 30 miles of 90210. It was duplicating some even though there are no dups in the zipcode database too, thus the DISTINCT u.id. Besides selecting only the columns I need, any ideas on how to speed this thing up?
<?php
$zipcode = queryDB("SELECT * FROM zipcodes WHERE zipcode='$location' LIMIT 1", 'a');
$distance = 30;
$sql = "SELECT DISTINCT zipcode, ( 3959 * acos( cos( radians(".$zipcode['lat'].") ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(".$zipcode['lon'].") ) + sin( radians(".$zipcode['lat'].") ) * sin( radians( lat ) ) ) ) AS distance FROM zipcodes HAVING distance <= $distance ORDER BY distance";
$zipcodes = queryDB($sql, 'r');
$sql = '';
while($row = mysqli_fetch_assoc($zipcodes)){
$sql .= "u.category='$category' AND u.zipcode='".$row['zipcode']."' AND u.zipcode = l.zipcode";
if($_GET['photos'] == 'y'){ $sql .= " AND photo_1!=''"; }
$sql .= " OR ";
}
$sql = rtrim($sql, ' OR ');
$profiles = queryDB("SELECT DISTINCT u.id, u.*, l.city, l.state, l.zipcode FROM user_accounts as u, zipcodes as l WHERE $sql ORDER BY date_added DESC", 'r');
while($row = mysqli_fetch_assoc($profiles)){
//this is where i display the profile information
} ?>
UPDATE: The biggest issue was not using a join on my user_accounts select. Here's my updated sql query.
$sql = '';
$zipcodes = new ZipCodesRange($location, $distance);
foreach ($zipcodes->zipCodes as $zipcode){
$sql .= "(u.category='$category' AND u.zipcode='".$zipcode['ZIPCODE']."'";
if($_GET['photos'] == 'y'){ $sql .= " AND photo_1!=''"; }
$sql .= ") OR ";
}
$sql = rtrim($sql, ') OR ');
$sql .= ")";
$profiles = queryDB("SELECT u.id, u.photo_1, u.name, u.business, u.date_added, l.city, l.state, l.zipcode FROM user_accounts as u INNER JOIN zipcodes as l ON u.zipcode = l.zipcode WHERE $sql ORDER BY date_added DESC", 'r');
Per #malias from this other question explaining the haversine formula, here is a document showing different ways to improve the speed of this sql: http://tr.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
The main goal is to limit the zipcodes being searched so that you don't have to calculate the haversine of so many records. The suggestion was to add a WHERE clause to filter the bounds of the latitude and longitude. Table indexes can be used for this rectangular filter, then the haversine can be used to filter it as a sphere.
I am running the following query in a PHP script:
$radius_query = "SELECT zip, ( 3959 * acos( cos( radians(" . $latitude .") ) * cos( radians( lat ) ) * cos( radians( lng ) - radians( " . $longitude . ") ) + sin( radians(" . $latitude .") ) * sin( radians( lat ) ) ) ) AS distance
FROM ZIP HAVING distance < ". $radius;
$radius_result = $db_zipcode->query($radius_query);
if (!$radius_result){
echo 'Could not run query: ' . mysql_error();
exit;
}
$row = $radius_result->fetch(PDO::FETCH_ASSOC);
While($row = $radius_result->fetch(PDO::FETCH_ASSOC))
{
$zip[] = $row['zip'];
}
foreach ($zip as $zip_display){
echo $zip_display . ", " . '';
}
The query itself works with one minor error - it does not return the first row of data. It should return a list of zip codes similar to this:
40324, 40339, 40340, 40347, 40356...
This is the result I get when I run the same query in phpMyAdmin.
However when I run the query above in a PHP script, the result set starts with 40339, and then includes all the remaining zip codes. Its not a mileage issue (i.e. the missing zip is well within the radius - as it shows up when I run the query in phpMyAdmin).
What am I doing wrong in the PHP query to miss that first row of data? Its not just a display problem because when I insert the query results in a DB, it is also missing the first row.
Thanks!
Problem is in the first fetch, they take your first row...
Run this without
$row = $radius_result->fetch(PDO::FETCH_ASSOC);
I had the same problem about a day ago.
There's no need to do an implicit loop in the PHP, try
$zip = $radius_result->fetchAll(PDO::FETCH_ASSOC);
I am having a serious problem converting my 'select' statement into something that will work with the zend paginator... could someone have a crack at it, as I am having no luck...
Here is my query:
$query = "SELECT
user_id, name, gender, city, province, country, image_id, one_liner, self_description, reputation
FROM
users
WHERE
(
(69.1 * (latitude - " . $user->latitude . ")) *
(69.1 * (latitude - " . $user->latitude . "))
) + (
(69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3)) *
(69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3))
) < " . pow($radius, 2) . "
ORDER BY
(
(69.1 * (latitude - " . $user->latitude . ")) *
(69.1 * (latitude - " . $user->latitude . "))
) + (
(69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3)) *
(69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3))
Here is what I have so far:
$select = $db->select();
$select->from(
array('users'),
array(
'user_id',
'name',
'gender',
'city',
'province',
'country',
'image_id',
'one_liner',
'self_description',
'reputation'
)
);
$select->where("(69.1 * (latitude - " . $user->latitude . ")) * (69.1 * (latitude - " . $user->latitude . "))) + ((69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3)) * (69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3))) < " . pow($radius, 2));
$select->order("(69.1 * (latitude - " . $user->latitude . ")) * (69.1 * (latitude - " . $user->latitude . "))) + ((69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3)) * (69.1 * (longitude - " . $user->longitude . ") * COS(" . $user->latitude . " / 57.3))) ASC");
Why do you have "<" in your order by clause?
What does this have to do with Zend_Paginator? Ah, do you have the query and you don't know how to make a paginator with it, or is the paginator not working with this query?
The only thing I can see is you're missing an opening parenthesis in both the where() and order() clause:
$select->where("((69.1 * [...] ");
$select->order("((69.1 * [...] ");
^
So maybe Zend_Paginator isn't working because the SQL query has errors?
And of course I have to ask: are those variables you're interpolating safe, or should you really be using $db->quote($user->latitude, Zend_Db::FLOAT_TYPE)?
Assuming you are using MVC-pattern, won't this work?
in your bootstrap:
Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination.phtml');
in your controller:
$page = Zend_Paginator::factory($select);
$page->setCurrentPageNumber($this->_getParam('page', 1));
$page->setItemCountPerPage($this->_getParam('par', 20));
$this->view->results= $page;
in your view:
<?php foreach($this->results as $result) : ?>
<!-- print some $result stuff here -->
<?php endforeach;?>
<?= $this->results ?>
then place a pagination.phtml example that you can find on zend manual
-Lo