I've the query
SELECT ID,
post_title,
post_author,
max(case when meta_key='geo_latitude' then meta_value end) latitude,
max(case when meta_key='geo_longitude' then meta_value end) longitude,
( 3959 * acos( cos( radians(18.204540500000) )
* cos( radians( latitude ) )
* cos( radians( longitude )
- radians(-66.450958500000) )
+ sin( radians(18.204540500000 ) )
* sin( radians( latitude ) )
)
) AS distance
FROM `wp_posts`
LEFT JOIN `wp_postmeta`
on ID=post_id
WHERE post_type='place'
AND (meta_key='geo_latitude' OR meta_key='geo_longitude')
GROUP BY ID, post_title, post_author
ORDER BY ID ASC
which results in
Error Code: 1054. Unknown column 'latitude' in 'field list'
Is there any way to solve this without using inner/nested queries?
Try this:
SELECT ID,
post_title,
post_author,
MAX(CASE WHEN meta_key='geo_latitude' THEN meta_value END) latitude,
MAX(CASE WHEN meta_key='geo_longitude' THEN meta_value END) longitude,
( 3959 * ACOS( COS( RADIANS(18.204540500000) )
* COS( RADIANS( MAX(CASE WHEN meta_key='geo_latitude' THEN meta_value END) ) )
* COS( RADIANS( MAX(CASE WHEN meta_key='geo_longitude' THEN meta_value END) )
- RADIANS(-66.450958500000) )
+ SIN( RADIANS(18.204540500000 ) )
* SIN( RADIANS( MAX(CASE WHEN meta_key='geo_latitude' THEN meta_value END) ) )
)
) AS distance
FROM `wp_posts`
LEFT JOIN `wp_postmeta`
ON ID=post_id
WHERE post_type='place'
AND (meta_key='geo_latitude' OR meta_key='geo_longitude')
GROUP BY ID, post_title, post_author
ORDER BY ID ASC
You can create a view:
create view geo as
select id, post_title, post_author,
max(case when meta_key='geo_latitude' then meta_value end) as latitude,
max(case when meta_key='geo_longitude' then meta_value end) as longitude
from wp_posts
where post_type='place'
and (meta_key='geo_latitude' OR meta_key='geo_longitude')
group by id, post_title, post_author;
and join your query with it instead of wp_posts:
SELECT ID,
post_title,
post_author,
latitude,
longitude,
( 3959 * acos( cos( radians(18.204540500000) )
* cos( radians( latitude ) )
* cos( radians( longitude )
- radians(-66.450958500000) )
+ sin( radians(18.204540500000 ) )
* sin( radians( latitude ) )
)
) AS distance
FROM `geo`
LEFT JOIN `wp_postmeta`
on ID=wp_postmeta.post_id
ORDER BY ID ASC;
Related
I am trying to the fetch nearest location according lat and lng but I want to add having distance < 5 clause in query.
But where I can use.??
select p.id, p.name, p_i.image as image,
( 3959 * acos( cos( radians(26.916279) ) *
cos( radians( lat ) ) *
cos( radians( lng ) - radians(75.8082) ) +
sin( radians(26.916279) ) *
sin( radians( lat ) ) ) ) AS distance
from `places` as p
inner join `place_images` as p_i
on p.`id` = p_i.`place_id`
where p.`city_id` = '1'
and p.status = 'active'
and p_i.display_order = '1'
limit 0, 5
current result
You can add having clause at last, just before limit
select p.id, p.name, p_i.image as image, ( 3959 * acos( cos( radians(26.916279) )
* cos( radians( lat ) ) * cos( radians( lng ) - radians(75.8082) )
+ sin( radians(26.916279) ) * sin( radians( lat ) ) ) ) AS distance
from `places` as p inner join `place_images` as p_i on p.`id` = p_i.`place_id`
where p.`city_id` = '1' and p.status = 'active' and p_i.display_order = '1'
HAVING distance < 5 limit 0, 5
Try this query
where p.`city_id` = '1' and p.status = 'active'
and p_i.display_order = '1'
HAVING distance < 5
limit 0, 5
use limit at last
select p.id, p.name, p_i.image as image, ( 3959 * acos( cos( radians(26.916279) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(75.8082) ) + sin( radians(26.916279) ) * sin( radians( lat ) ) ) ) AS distance from `places` as p inner join `place_images` as p_i on p.`id` = p_i.`place_id`
where p.`city_id` = '1'
and p.status = 'active'
and p_i.display_order = '1'
HAVING distance < 5 # add this
limit 0, 5
I realize that this doesn't directly translate from MSSQL to MySQL but I'm not not sure how to make it work. Any help that you have is appreciated.
;WITH cte As (
SELECT
post_id,
status,
dealer,
distributor,
SUM(
3959 * acos(
cos( radians(%f) ) *
cos( radians( lat ) ) *
cos( radians( lng ) - radians(%f) ) +
sin( radians(%f) ) *
sin( radians( lat ) )
)
)
AS DISTANCE
FROM wp_geodatastore
GROUP BY post_id, status, dealer, distributor
)
SELECT post_id, status, dealer, distributor, DISTANCE
FROM cte WHERE (DISTANCE < %d)
AND status = 'publish' AND dealer = 'on' AND distributor = 'on'
ORDER BY DISTANCE
OFFSET %d ROWS
FETCH NEXT %d ROWS ONLY;
Just make it a subquery:
SELECT post_id, status, dealer, distributor, DISTANCE
FROM (SELECT post_id, status, dealer, distributor,
SUM( 3959 * acos(
cos( radians(%f) ) *
cos( radians( lat ) ) *
cos( radians( lng ) - radians(%f) ) +
sin( radians(%f) ) *
sin( radians( lat ) )
)
) AS DISTANCE
FROM wp_geodatastore
GROUP BY post_id, status, dealer, distributor
) cte
WHERE (DISTANCE < %d) AND
status = 'publish' AND dealer = 'on' AND distributor = 'on'
ORDER BY DISTANCE
OFFSET %d ROWS
FETCH NEXT %d ROWS ONLY;
I have the following SQL statement:
SELECT Distinct(Venue_Name), Count(*) as `num1`
FROM venuetagview
INNER JOIN
(
SELECT Tag,COUNT(*) AS `num`
FROM usertags
WHERE UserID=4
GROUP BY Tag
ORDER BY `num` DESC
) as a
ON venuetagview.Tag=a.Tag
GROUP BY Venue_Name
ORDER BY `num1` DESC
And I am trying to add a 'distance' calculation into it, using the latitude/longitude I have in the venuetagview table. I have tried this:
SELECT
( 6371
* acos( cos( radians(51.529099) )
* cos( radians( Venue_Latitude ) )
* cos( radians( Venue_Longitude )
- radians(-0.084981) )
+ sin( radians(51.529099) )
* sin( radians( Venue_Latitude ) ) ) ) AS distance,
Distinct(Venue_Name),
Count(*) as `num1`
FROM venuetagview
INNER JOIN
(
SELECT Tag,
COUNT(*) AS `num`
FROM usertags
WHERE UserID=4
GROUP BY Tag
ORDER BY `num` DESC
) as a
ON venuetagview.Tag=a.Tag
GROUP BY Venue_Name
ORDER BY `num1` DESC
However I am getting an error using this.
Only issue I see with your posted query is
distinct is keywork and should be used like distinct column_name
SELECT Distinct (Venue_Name) should just be SELECT Venue_Name or
SELECT Distinct Venue_Name
As mentioned by Strawberry removing DISTINCT solved this:
SELECT
( 6371 * acos( cos( radians(51.529099) )
* cos( radians( Venue_Latitude ) )
* cos( radians( Venue_Longitude )
- radians(-0.084981) )
+ sin( radians(51.529099) )
* sin( radians( Venue_Latitude ) ) ) ) AS distance,
Venue_Name,
Count(*) asnum1
FROM venuetagview
INNER JOIN
(
SELECT Tag,
COUNT(*) ASnum
FROM usertags
WHERE UserID=4
GROUP BY Tag
ORDER BYnumDESC) as a
ON venuetagview.Tag=a.Tag
GROUP BY Venue_Name
ORDER BY distance ASC
I'm trying to get nearest places from a WordPress database using Haversine formula
My table structure below
posts
+--------------+
| Field |
+--------------+
| ID |
| post_author |
| post_title |
| post_type |
+--------------+
postmeta
+--------------+
| Field |
+--------------+
| meta_id |
| post_id |
| meta_key |
| meta_value |
+--------------+
and have records with meta_key values latitude and longitude
See the answer to my previous question for the SQL I've used to get the latitude and longitude.
SELECT p.ID,
p.post_title,
p.post_author,
max(case when pm.meta_key='latitude' then pm.meta_value end) latitude,
max(case when pm.meta_key='longitude' then pm.meta_value end) longitude
FROM `wp_posts` p
LEFT JOIN `wp_postmeta` pm
on p.ID=pm.post_id
WHERE p.post_type='place'
AND (pm.meta_key='latitude' OR pm.meta_key='longitude')
GROUP BY p.ID, p.post_title, p.post_author
ORDER BY p.ID ASC
Now I want to incorporate above query into answer for this question
SELECT item1, item2,
( 3959 * acos( cos( radians(37) )
* cos( radians( lat ) )
* cos( radians( lng )
- radians(-122) )
+ sin( radians(37) )
* sin( radians( lat ) )
)
) AS distance
FROM geocodeTable
HAVING distance < 25
ORDER BY distance LIMIT 0 , 20;
Below is by combined query
SELECT ID,
post_title,
post_author,
max(case when meta_key='latitude' then meta_value end) latitude,
max(case when meta_key='longitude' then meta_value end) longitude,
( 3959 * acos( cos( radians(18.204540500000) )
* cos( radians( latitude ) )
* cos( radians( longitude )
- radians(-66.450958500000) )
+ sin( radians(18.204540500000 )
* sin( radians( latitude ) )
)
) AS distance
FROM `wp_posts`
LEFT JOIN `wp_postmeta`
on ID=post_id
WHERE post_type='place'
AND (meta_key='latitude' OR meta_key='longitude')
GROUP BY ID, post_title, post_author
ORDER BY ID ASC
But this yields syntax error
#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 'AS distance FROM `wp_posts` LEFT JOIN `wp_postmeta` on ID=post_id WHERE po' at line 13
You are missing a closing ) for the first sin()
( 3959 * acos( cos( radians(18.204540500000) )
* cos( radians( latitude ) )
* cos( radians( longitude )
- radians(-66.450958500000) )
+ sin( radians(18.204540500000 ) ) /* <--- here */
* sin( radians( latitude ) )
)
) AS distance
Though it is difficult to spot visually, I found this by copying your code into a text editor that supports brace matching. It is highly recommended to use one, if not for query development and testing, then at least for debugging.
Try this:
SELECT *, ( 3959 * ACOS( COS( RADIANS(18.204540500000) )
* COS( RADIANS( latitude ) )
* COS( RADIANS( longitude )
- RADIANS(-66.450958500000) )
+ SIN( RADIANS(18.204540500000 ) )
* SIN( RADIANS( latitude ) )
)
) AS distance
FROM
(SELECT ID,
post_title,
post_author,
MAX(CASE WHEN meta_key='geo_latitude' THEN meta_value END) latitude,
MAX(CASE WHEN meta_key='geo_longitude' THEN meta_value END) longitude
FROM `wp_posts`
LEFT JOIN `wp_postmeta`
ON ID=post_id
WHERE post_type='place'
AND (meta_key='geo_latitude' OR meta_key='geo_longitude')
GROUP BY ID, post_title, post_author
ORDER BY ID ASC) AS A
My current code
SELECT post_id, ( 3959 * ACOS( COS( RADIANS( 34.09 ) ) * COS( RADIANS( lat ) ) * COS( RADIANS( lng ) - RADIANS( -117.55 ) ) + SIN( RADIANS( 34.09 ) ) * SIN( RADIANS( lat ) ) ) ) AS distance FROM wp_postmeta WHERE `meta_key` LIKE '%location_l%' HAVING distance < 2500 ORDER BY distance LIMIT 0 , 20
Here are two sample row of data (meta_key is not always long or lat):
post_id = 123
meta_key = location_longitude
meta_value = -119.890000
post_id = 123
meta_key = location_latitude
meta_value = 42.170000
How do I modify my query to replace 'lat' and 'lng' in my original query to be the contents of the meta_value listed above? Something like this?
select meta_value where meta_key = location_latitude
If you GROUP BY post_id, you should be able to use MAX() aggregates in place of lat,lng, surrounding CASE statements which determine whether the current row is latitude or longitude. The others will be NULL, and therefore eliminated by the aggregate.
I think this ought to work so you won't need any subselects.
SELECT
post_id,
( 3959 * ACOS( COS( RADIANS( 34.09 ) ) * COS( RADIANS( MAX(CASE WHEN meta_key='location_latitude' THEN meta_value ELSE NULL END) ) ) * COS( RADIANS( MAX(CASE WHEN meta_key='location_longitude' THEN meta_value ELSE NULL END) ) - RADIANS( -117.55 ) ) + SIN( RADIANS( 34.09 ) ) * SIN( RADIANS( MAX(CASE WHEN meta_key='location_latitude' THEN meta_value ELSE NULL END) ) ) ) ) AS distance
FROM wp_postmeta
WHERE `meta_key` IN ('location_latitude','location_longitude')
GROUP BY post_id
HAVING distance < 2500
ORDER BY distance
LIMIT 0 , 20
The moving parts here are:
MAX(CASE WHEN meta_key='location_latitude' THEN meta_value ELSE NULL END)
This translates as: If this row's meta_key is 'location_latitude', return the meta_value, otherwise return NULL. We expect then that since two rows are returned for the post_id (lat,lng), the MAX() value returned above is always the non-null one -- the correct latitude or longitude value from meta_value.
You need to join the table to itself (this is common in databases with EAV structure):
SELECT
post_id,
distance
FROM
( SELECT
lng.post_id,
( 3959 * ACOS( COS( RADIANS( 34.09 ) )
* COS( RADIANS( lat.meta_value ) )
* COS( RADIANS( lng.meta_value )
- RADIANS( -117.55 ) )
+ SIN( RADIANS( 34.09 ) )
* SIN( RADIANS( lat.meta_value ) )
)
) AS distance
FROM wp_postmeta AS lng
JOIN wp_postmeta AS lat
ON lat.post_id = lng.post_id
WHERE lng.meta_key = 'location_longitude'
AND lat.meta_key = 'location_latitude'
) AS tmp
WHERE distance < 2500
ORDER BY distance
LIMIT 0 , 20 ;
One approach is to replace the reference to the table (i.e. FROM wp_postmeta) in your query with an inline view, something like this:
FROM
( SELECT plat.post_id
, plat.meta_value AS lat
, plng.meta_value AS lng
FROM wp_postmeta plat
JOIN wp_postmeta plng
ON plat.post_id = plng.post_id
AND plat.meta_key = 'location_latitude'
AND plng.meta_ley = 'location_longitude'
) wpm
(NOTE: this assumes that there is only one row for each post_id for each of the two meta_key values of interest...)
This uses an "inline view" to combine the latitude and longitude values for each post_id into a single row. (You can run just the query for the inline view to confirm that its returning the results you expect.) We can use an inline view in place of a table reference, in more recent versions of MySQL (version >= 5.0).
SELECT a.post_id,
( 3959 * ACOS( COS( RADIANS( 34.09 ) ) * COS( RADIANS( lat.meta_value ) ) * COS( RADIANS( lng.meta_value ) - RADIANS( -117.55 ) ) + SIN( RADIANS( 34.09 ) ) * SIN( RADIANS( lat.meta_value ) ) ) ) AS distance
FROM wp_postmeta lat, wp_postmeta lng
WHERE lat.post_id = lng.postID
AND lat.meta_key = 'location_latitude'
AND lng.meta_key = 'location_longitude'
HAVING distance < 2500
ORDER BY distance LIMIT 0 , 20