MySQL: Combining two queries into one row result - mysql

First part of the query:
SET #centerLat = '48.531157';
SET #centerLng = '-123.782959';
SELECT user_id, lat, lng, ( 3959 * acos( cos( radians( #centerLat ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(#centerLng) ) + sin( radians( #centerLat ) ) * sin( radians( lat ) ) ) ) AS distance FROM bid_userloc HAVING distance < 25 ORDER BY distance LIMIT 0 , 20
Second aspect is taking the user_id and grabbing a bunch of information from the USERS table
I'm still learning what JOIN even means and I don't quite understand how it all works best...

you may try this
SELECT user_id, lat, lng, ( 3959 * acos( cos( radians( #centerLat ) )
* cos( radians( lat ) ) * cos( radians( lng ) - radians(#centerLng) )
+ sin( radians( #centerLat ) ) * sin( radians( lat ) ) ) )
AS distance,columnsfromuserstable FROM bid_userloc bid
inner join users us on bid.user_id=us.user_id
HAVING distance < 25
ORDER BY distance LIMIT 0 , 20

You can try something like this:
select * from users where user_id in (select user_id from(
SELECT user_id, lat, lng, ( 3959 * acos( cos( radians( #centerLat ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(#centerLng) ) + sin( radians( #centerLat ) ) * sin( radians( lat ) ) ) ) AS distance FROM bid_userloc HAVING distance < 25 ORDER BY distance LIMIT 0 , 20
));

Variant with JOIN -
SET #centerLat = '48.531157';
SET #centerLng = '-123.782959';
SELECT
t1.user_id, t1.lat, t1.lng,
(3959 * ACOS(COS(RADIANS(#centerLat)) * COS(RADIANS(t1.lat)) * COS(RADIANS(t1.lng) - RADIANS(#centerLng)) + SIN(RADIANS(#centerLat)) * SIN(RADIANS(t1.lat)))) distance,
t2.*
FROM
bid_userloc t1
JOIN users t2
ON t1.user_id = t2.user_id
HAVING
distance < 25
ORDER BY
distance
LIMIT
0, 20;

Related

How to get values from another table and insert the result into another query

I am trying to to build a basic sql query where I have a table of petrol stations and another table of POI in my sql database and I would like to get all petrol stations within a radius of a POI
I have the following query:
SELECT *, ( 6371000 * acos( cos( radians(15.4383252) )
* cos( radians( petrol_stations.lat ) ) * cos( radians( petrol_stations.lng ) - radians(47.0450591) )
+ sin( radians(15.4383252) ) * sin(radians(petrol_stations.lat)) ) )
AS distance FROM petrol_stations HAVING distance < 500
and it seems to work fine, however I have to hard-code the coordinates of the POI into the query. Is it possible to adapt the query such that the POI coordinates are pulled from the other table if provided with the name such as main square?
Thanks in advance.
assuming you have a georef poi table as
table_poi
id name lat lng
1 my_poi 47.0450591 15.4383252
you could try a cross join for related all your petrol_stations with all your POI
SELECT *
, ( 6371000 * acos( cos( radians(table_poi.lng) )
* cos( radians( petrol_stations.lat ) ) * cos( radians( petrol_stations.lng )
- radians(table_poi.lat) )
+ sin( radians(table_poi.lng) ) * sin(radians(petrol_stations.lat)) ) )
AS distance
FROM petrol_stations
CROSS JOIN table_poi
HAVING distance < 500
or using where (as requested by MarlinPierce)
SELECT *
, ( 6371000 * acos( cos( radians(table_poi.lng) )
* cos( radians( petrol_stations.lat ) ) * cos( radians( petrol_stations.lng )
- radians(table_poi.lat) )
+ sin( radians(table_poi.lng) ) * sin(radians(petrol_stations.lat)) ) )
AS distance
FROM petrol_stations
CROSS JOIN table_poi
WHERE ( 6371000 * acos( cos( radians(table_poi.lng) )
* cos( radians( petrol_stations.lat ) ) * cos( radians( petrol_stations.lng )
- radians(table_poi.lat) )
+ sin( radians(table_poi.lng) ) * sin(radians(petrol_stations.lat)) ) ) < 500
and if you want filter for a POI name
SELECT *
, ( 6371000 * acos( cos( radians(table_poi.lng) )
* cos( radians( petrol_stations.lat ) ) * cos( radians( petrol_stations.lng )
- radians(table_poi.lat) )
+ sin( radians(table_poi.lng) ) * sin(radians(petrol_stations.lat)) ) )
AS distance
FROM petrol_stations
WHERE table_poi.name like '%your_poi_name%'
CROSS JOIN table_poi
HAVING distance < 500

Counting records in MySQL with a complicated HAVING Statement

I have a query which returns map markers within a radius (in miles) of a given position (lat/lng). My query works when reading the data, but I am wanting to set up pagination so need to count the records first to determine how many pages of data I will have.
My query is :
SET #LAT := 53.068464;
SET #LNG := -4.076113;
SET #Miles := 10;
SELECT (3959 * acos( cos( radians(#LAT) ) * cos( radians( M.Lat ) ) * cos(
radians( M.Lng ) - radians(#LNG) ) + sin( radians(#LAT) ) * sin( radians(
M.Lat ) ) ) ) AS distance, M.MarkerId, M.Title
FROM Markers AS M
HAVING distance < #Miles
ORDER BY M.DateStamp desc, Distance
I have tried
SELECT COUNT(MarkerId)
FROM Markers
HAVING (3959 * acos( cos( radians(#LAT) ) * cos( radians( Lat ) ) * cos(
radians( Lng ) - radians(#LNG) ) + sin( radians(#LAT) ) * sin( radians( Lat )
) ) ) < #Miles
but it fails trying to reference the Lat and Lng fields from the Markers table.
There are two methods. One is to use a subquery:
SELECT COUNT(*)
FROM (SELECT (3959 * acos( cos( radians(#LAT) ) * cos( radians( M.Lat ) ) * cos(
radians( M.Lng ) - radians(#LNG) ) + sin( radians(#LAT) ) * sin( radians(
M.Lat ) ) ) ) AS distance, M.MarkerId, M.Title
FROM Markers AS M
HAVING distance < #Miles
) x
The second method is to use SQL_CALC_FOUND_ROWS and then the FOUND_ROWS() function:
SELECT SQL_CALC_FOUND_ROWS (3959 * acos( cos( radians(#LAT) ) * cos( radians( M.Lat ) ) * cos(
radians( M.Lng ) - radians(#LNG) ) + sin( radians(#LAT) ) * sin( radians(
M.Lat ) ) ) ) AS distance, M.MarkerId, M.Title
FROM Markers AS M
HAVING distance < #Miles
ORDER BY M.DateStamp desc, Distance ;
SELECT FOUND_ROWS();
$str1="select SQL_CALC_FOUND_ROWS (3959 * acos( cos( radians(#LAT) ) * cos( radians( M.Lat ) ) * cos(
radians( M.Lng ) - radians(#LNG) ) + sin( radians(#LAT) ) * sin( radians(
M.Lat ) ) ) ) AS distance, M.MarkerId, M.Title
FROM Markers AS M
HAVING distance < #Miles
ORDER BY M.DateStamp desc, Distance limit ".$offset.",".$limit;
$q1 = mysql_query($str1);
$result=array();
$str2="SELECT FOUND_ROWS() AS Count";
$q2 = mysql_query($str2);
while($objCount= $q2->fetch_assoc()) {
$result["TotalRows"] = $objCount['Count'];
}
if ($q1->num_rows > 0) {
$result["Rows"] = mysql_result($q1);
} else {
$result["Rows"] = array();
}
return $result;

Haversine formula returns null in Query

SELECT
id,
( 3959 * acos( cos( radians(51.509980) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-0.133700 ) ) + sin( radians(51.509980) ) * sin(radians(lat)) ) ) AS distance
FROM tbl_event
HAVING distance < 5
ORDER BY distance
Here -0.133700 is creating problem, other minus values like -122 etc. are working fine with this.
Please help if anyone is aware of this issue.
It returns null because acos function get an argument greater than 1 or lower than -1. Try this :
Select id, 3959 * acos(if(d>1, 1, if(d<-1, -1, d))) as distance
From (SELECT id,
cos( radians(51.509980) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-0.133700 ) ) + sin( radians(51.509980) ) * sin(radians(lat)) AS d
FROM tbl_event ) t1
HAVING distance < 5
ORDER BY distance

How to hide an alias column in mysql EDITED

I know this is a replica of some question asked already, but i need some suggestion.
I know basics of MySQL, i have a query to calculate distance between latitude and longitude and based on minimum distance i am returning id's.
now i don't want the distance column as result of my query. How to do it.
Here is my query.
select cl.wp_id,( 3959 * acos( cos( radians(12.91841) ) * cos( radians( y(gproperty) ) ) *
cos( radians( x(gproperty)) - radians(77.58631) ) + sin( radians(12.91841) ) *
sin( radians(y(gproperty) ) ) ) ) AS distance
from db1.geofeature gf, db2.c_loc cl where gf.o_type = 10 and cl.c_info_id = 23
and gf.o_id = cl.wp_id
having distance < 10 order by distance limit 10;
i want only my cl.wp to be displayed as result. How to do that.?
EDIT
now i have 3 tables how to join them.?
select dlo.id,( 3959 * acos( cos( radians(12.9) ) * cos( radians( y(gproperty) ) ) * cos( radians( x(gproperty)) - radians(77.5) ) +sin( radians(12.9) ) * sin( radians(y(gproperty) ) ) ) ) AS distance from db1.gfeature dgf, db2.loc dlo, db2.cust dcu where gf.o_type = 6 and dcu.id = 240 and dgf.o_id = dlo.p_id having distance < 20 order by distance limit 10;
Any suggestions are welcome.
You would want to use a subquery:
select wp_id
from (select cl.wp_id,( 3959 * acos( cos( radians(12.91841) ) * cos( radians( y(gproperty) ) ) *
cos( radians( x(gproperty)) - radians(77.58631) ) + sin( radians(12.91841) ) *
sin( radians(y(gproperty) ) ) ) ) AS distance
from db1.geofeature gf join
db2.c_loc cl
on gf.o_type = 256 and cl.c_info_id = 146 and gf.o_id = cl.wp_id
) t
where distance < 10
order by distance
limit 10;
Notice that I also fixed the join syntax to use explicit joins.

MySQL - Ordered GROUP BY Issue Optimization

I have a table called stores which contains store information and more importantly location coordinates of stores of various merchants. A merchant can have multiple stores at various locations. I need a listing of stores ordered by distance (from a particular location) with only the closest store of each merchant showing in the list.
The following query works but I believe its sub-optimal. Is there a way to revise or improve this query?
SELECT
`Store`.`id`,
`Merchants`.`id`,
`Store`.`area_id`,
`Store`.`url`,
( 6371 * acos( cos( radians(18.973212066666665) ) * cos( radians( Store.latitude ) ) * cos( radians( Store.longitude ) - radians(72.8140959) ) + sin( radians(18.973212066666665) ) * sin( radians( Store.latitude ) ) ) ) AS distance
FROM
`stores` AS `Store`
INNER JOIN
(SELECT DISTINCT id,( 6371 * acos( cos( radians(18.973212066666665) ) * cos( radians( Store.latitude ) ) * cos( radians( Store.longitude ) - radians(72.8140959) ) + sin( radians(18.973212066666665) ) * sin( radians( Store.latitude ) ) ) ) AS distance FROM stores as Store WHERE Store.active=1 AND Store.parent_id=0 AND (( 6371 * acos( cos( radians(18.973212066666665) ) * cos( radians( Store.latitude ) ) * cos( radians( Store.longitude ) - radians(72.8140959) ) + sin( radians(18.973212066666665) ) * sin( radians( Store.latitude ) ) ) ) < 50) GROUP BY Store.id ORDER BY distance) AS `St` ON (`St`.`id` = `Store`.`id`)
INNER JOIN
merchants AS `Merchants` ON (`Store`.`merchant_id` = `Merchants`.`id`)
WHERE
(( 6371 * acos( cos( radians(18.973212066666665) ) * cos( radians( `Store`.`latitude` ) ) * cos( radians( `Store`.`longitude` ) - radians(72.8140959) ) + sin( radians(18.973212066666665) ) * sin( radians( `Store`.`latitude` ) ) ) ) < 50) AND
`Store`.`parent_id` = 0 AND
`Store`.`active` = 1
GROUP BY
`Merchants`.`id`
ORDER BY
`distance` ASC
LIMIT 10
I am using the following formula to calculate distance ( 6371 * acos( cos( radians(LATITUDE) ) * cos( radians( Store.latitude ) ) * cos( radians( Store.longitude ) - radians(LONGITUDE) ) + sin( radians(LATITUDE) ) * sin( radians( Store.latitude ) ) ) )
Looks like you don't need the merchant table at all. You are using it only for merchant_id which you have in the store table anyways. So you can avoid this join.
If I understand what you need correctly, you can try this query:
select id, merchant_id, area_id, url,
min(distance function you are using) as distance
from stores group by merchant id, order by distance
I did not actually run it, but the idea should work.
-Mansi