MySQL query returning errors - mysql

I'm trying to get coordinates and locations from a database, but my server is returning this error:
Error: You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near
'long ) - radians(0) ) + sin( radians(0) ) * sin( radians( lat ) ) ) ) AS distanc'
at line 1
Query:
SELECT id,
address,
name,
(3959 * acos(cos(radians(0)) *
cos(radians(lat)) *
cos(radians(long) - radians(0)) +
sin(radians(0)) *
sin(radians(lat)))
) AS distance
FROM places
HAVING distance < 10
ORDER BY distance
LIMIT 0, 20;
Do I have to escape "lat" and "long" with `, or is that formula wrong altogether? Thanks.
Also, the coordinates I'm using are 0, 0 (just for test purposes).

LONG is a reserved word in mysql. Escape it using backticks when using it as a column name.

Replace the HAVING statement with "WHERE" statement. There is no "GROUP BY", then why are you using HAVING?

I think you have an extra ). Try this
SELECT id, address, name, ( 3959 * acos( cos( radians(0) ) * cos( radians( lat ) ) * cos( radians( long ) - radians(0) ) + sin( radians(0) ) * sin( radians( lat ) ) ) AS distance FROM places HAVING distance < 10 ORDER BY distance LIMIT 0 , 20;

Related

How to cast string parameter to int in a "limit"

SELECT DISTINCT(id) vetid,
c.clinic_id,
c.clinic_name,
c.type,
c.city,
c.state,
c.country,
c.lat,
c.lng,
c.zip,
( 3959 * Acos( Cos( Radians(44.977498) ) * Cos( Radians( c.lat ) ) * Cos( Radians( c.lng ) - Radians(-93.406556) ) + Sin( Radians(44.977498) ) * Sin( Radians( c.lat ) ) ) ) AS distance
FROM biah_clinics c
WHERE opt_out != '1'
AND c.country = 'US'
HAVING distance < '10'
ORDER BY distance limit cast('20' AS int);
Using Drupal's db_query, all parameters passed to the query are passed as STRING. This is giving me an error. That is why in my query, I want to cast that parameter to INT.
So it should end up like this:
limit cast('20' AS int);
limit 20;
But this is giving me an error in MySQL:
"SQLSTATE[42000]: Syntax error or access violation: 1064 You have an
error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'CAST('25' AS
INT)' at line 15"
I ended up using drupal's db_query_range(), due to sql limit doesn't work but with integer literals.
https://api.drupal.org/api/drupal/includes%21database%21database.inc/function/db_query_range/7.x

Using result of first select statement into another and store result into another table

After a lot of reading I have written these 3 sql statement and I want to automate and combine these 3 sql statement.
select longitude,latitude from roadData;
SELECT geo_coordinates_latitude, geo_coordinates_longitude,
( 3959 * acos( cos( radians('-37.964637158') ) * cos( radians( geo_coordinates_latitude ) ) *
cos( radians( geo_coordinates_longitude ) - radians('144.408476215') ) + sin( radians('-37.964637158') ) *
sin( radians( geo_coordinates_latitude ) ) ) ) AS distance
FROM tweetmelbourne HAVING distance < .1 ORDER BY distance LIMIT 0 , 20;
Insert into roadTweets(longitude,latitude) values(144.408476215,-37.964637158);
**
What basically i want to do is pick all the coordinates from roadData
one by one and then find all the point in tweetMelbourne within 20
miles of it and insert those point into another table.
**
describe tweetmelbourne;
describe roadData;
I'm not enterily sure on this, so please let me know if this works:
Insert into roadTweets(longitude,latitude) values(SELECT geo_coordinates_latitude, geo_coordinates_longitude,
( 3959 * acos( cos( radians(SELECT latitude FROM roadData) ) * cos( radians( geo_coordinates_latitude ) ) *
cos( radians( geo_coordinates_longitude ) - radians(SELECT longitude FROM roadData) ) + sin( radians(latitude) ) *
sin( radians( geo_coordinates_latitude ) ) ) ) AS distance
FROM tweetmelbourne HAVING distance < .1 ORDER BY distance LIMIT 0 , 20);
I guess this should be:
select * from tweetmelbourne t, roadData r
where distance(r.longitude,r.latitude,t.geo_coordinates_longitude,t.geo_coordinates_latitude) < 20;
And either implement distance funcion or replace distance(r.longitude,r.latitude,t.geo_coordinates_longitude,t.geo_coordinates_latitude) with formula calculating distance so. In oracle you can use package SDO_GEOMETRY.

MySQL sub query with two columns - how to hide the second column?

I'm having a difficult time wrapping my head around how to do this, even with all the searching and reading I've done on this!
I have a query I am using to try to pull all users from a database that have a zip code that falls within a certain distance of a given decimal coordinate. Here's the query that I am running:
select distinct watch_list.username, enabled
from watch_list, registered_users
where watch_list.username = registered_users.username AND watch_list.watchzip = (
SELECT zip,
( 3959 * acos( cos( radians('29.7632800') ) *
cos( radians( lat ) ) *
cos( radians( lng ) -
radians('-95.3632700') ) +
sin( radians('29.7632800') ) *
sin( radians( lat ) ) ) )
AS distance from zip
HAVING distance <= '10');
There error I get back is expected, as my sub query is returning two columns:
MySQL said: Documentation
#1241 - Operand should contain 1 column(s)
How can I do this and filter on the distance without the sub query returning both columns?
P.S. Just for completion and information sake, the "zip" table contains a list of all zip codes in the U.S. along with their decimal coordinates.
Just move the operation out of the column list:
select distinct watch_list.username, enabled
from watch_list, registered_users
where watch_list.username = registered_users.username
AND watch_list.watchzip = (
SELECT zip
from zip
WHERE ( 3959 * acos( cos( radians('29.7632800') ) *
cos( radians( lat ) ) *
cos( radians( lng ) -
radians('-95.3632700') ) +
sin( radians('29.7632800') ) *
sin( radians( lat ) ) ) ) <= '10');
Edit: As P.Salmon mentions, you probably also want to change AND watch_list.watchzip = to AND watch_list.watchzip IN.

Why won't this query return results that are 0?

Using haversine, the following query finds all rows that have coordinates within a 10 mile radius of the inputted coordinates.
SELECT *
, ( 3959 * acos( cos( radians($locationLatitude) )
* cos( radians( endingLatitude ) )
* cos( radians( endingLongitude ) - radians( $locationLongitude ) )
+ sin( radians( $locationLatitude) )
* sin( radians( endingLatitude ) ) ) ) AS distance
FROM trips
HAVING distance < 10
ORDER
BY distance
LIMIT 0 , 10;
However, it does not return rows that have the same exact coordinates as the coordinates inputted. Why is this?
You're using incorrect syntax: Change HAVING to WHERE and use a subquery so you can refer to the alias of the calculation rather than having to repeat the formula:
select * from (
select *, ( 3959 * acos( cos( radians($locationLatitude) )
* cos( radians( endingLatitude ) )
* cos( radians( endingLongitude ) - radians( $locationLongitude ) )
+ sin( radians( $locationLatitude) )
* sin( radians( endingLatitude ) ) ) ) AS distance
from trips) x
WHERE distance < 10
ORDER BY distance
LIMIT 0, 10
HAVING is for conditions on aggregated values for groups, eg GROUP BY FOO HAVING COUNT(*) > 3, but you aren't doing any grouping; you need a simple where clause.
Unfortunately, mysql has "lenient" grouping syntax which has allowed your statement to execute without a syntax error, even though it is logically unsound. The same query run on other databases would cause an error.

How to improve this huge SQL query?

I have a big SQL query (for MySQL) that is slow. It's a union of two select statements. I have tried different things, but any slight variance gives me a different result set from the original. Any help with improving it will be greatly appreciated. Thanks. Here is the SQL:
(SELECT
CONCAT(city_name,', ',region) value,
latitude,
longitude,
id,
population,
( 3959 * acos( cos( radians($latitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($longitude) ) + sin( radians($latitude) ) * sin( radians( latitude ) ) ) )
AS distance,
CASE region
WHEN '$region' THEN 1
ELSE 0
END AS region_match
FROM `cities`
$where and foo_count > 5
ORDER BY region_match desc, foo_count desc
limit 0, 11)
UNION
(SELECT
CONCAT(city_name,', ',region) value,
latitude,
longitude,
id,
population,
( 3959 * acos( cos( radians($latitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($longitude) ) + sin( radians($latitude) ) * sin( radians( latitude ) ) ) )
AS distance,
CASE region
WHEN '$region' THEN 1
ELSE 0
END AS region_match
FROM `cities`
$where
ORDER BY region_match desc, population desc, distance asc
limit 0, 11)
limit 0, 11
The SQL does take some interpolated values (prefixed with the dollar sign($)).
The following might give the same result (I'm not sure about how the maximum/minimum functions are called in SQL, but you should get an idea -- you need two fields derived from foo_count which separate the items of the first part of your UNION from those of the second one and allow ordering within the first part without disturbing the order in the second part) -- of course, you later need a second query to throw the additional fields out again:
SELECT
CONCAT(city_name,', ',region) value,
latitude,
longitude,
id,
population,
( 3959 * acos( cos( radians($latitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($longitude) ) + sin( radians($latitude) ) * sin( radians( latitude ) ) ) )
AS distance,
min ( 6, max (foo_count, 5)) AS group_discriminator,
max ( 6, foo_count) AS rank_for_use_in_first_group,
CASE region
WHEN '$region' THEN 1
ELSE 0
END AS region_match
FROM `cities`
$where
ORDER BY group_discriminator desc, region_match desc, rank_for_use_in_first_group desc, population desc, distance asc
limit 0, 11
EDIT: Improvements