Merging 2 sql queries into a single one - mysql

I have two sql queries which when run independent produces the correct results
Query 1
SELECT id,
(6371 * acos( cos( radians(9.977364864079215) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.58620953448485) ) + sin( radians(9.977364864079215) ) * sin( radians( latitude ) ) ) )
AS distance
FROM geodata HAVING distance < 20
ORDER BY distance
LIMIT 0 , 20;
Query 2
SELECT DISTINCT e.* FROM schools e
WHERE (
(e.type = 'preprimary')
)
AND(
e.title LIKE '%government%'
)
LIMIT 0, 10
I want to merge the first query with the second one, so that it should return all "preprimary" type schools with title like "government" located within 20KM radius and the result needs to be ordered by the distance.
How can I merge the two queries? I tried using JOINING the geodata table on the school table. But I dont know the remaining. Sorry, if this is a silly question. I am pretty new to SQL world.

SELECT DISTINCT school.* FROM
( SELECT geodata.id,
(6371 * acos( cos( radians(9.977364864079215) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.58620953448485) ) + sin( radians(9.977364864079215) ) * sin( radians( latitude ) ) ) )
AS distance ,school.*
FROM geodata LEFT JOIN school on geodata.id=school.id
WHERE
(school.type = 'preprimary')
AND(
school.title LIKE '%government%'
)
AND school.id IS NOT NULL
HAVING distance < 20 )x
ORDER BY x.distance
LIMIT 0 , 10;

Try this:
SELECT *
From (
SELECT DISTINCT e.* ,
(6371 * acos( cos( radians(9.977364864079215) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.58620953448485) ) + sin( radians(9.977364864079215) ) * sin( radians( latitude ) ) )
) as distance
FROM schools e
LEFT JOIN geodata g ON e.id=g.id
WHERE (e.type = 'preprimary')
AND ( e.title LIKE '%government%' )
) as s
Where s.distance < 20
Order by s.distance

Related

Virtual column unknown when comparing lat lng

I am attempting to return only rows where the latitude and longitude being passed into the query, when compared to the latitude and longitude stored in the database, is a certain amount of miles apart.
The query is as follows:
SELECT
c.google_theatre_id
AS cinema_id,
c.name
AS cinema_name,
( 3959 * acos( cos( radians('50.4521013') ) *
cos( radians( latitude ) ) *
cos( radians( longitude ) -
radians('-3.5247389') ) +
sin( radians('50.4521013') ) *
sin( radians( latitude ) ) ) )
AS distance
FROM
google_cinemas c, app_users u
WHERE
distance < u.range
AND
u.id = 126
ORDER BY
distance
The query is designed to get the distance and then compare it to a column (range) in the app_users table.
When running the query, I'm getting an error of distance being an unknown column.
As this is a virtual column, is there a different way of comparing?
Thanks :)
you need to use HAVING instead of WHERE.. think of it this way WHERE is when you make an order at a restraunt and HAVING is picking stuff off of the plate when it comes to your table... you cannot reference an alias before the plate comes to your table only after it has been built
SELECT
c.google_theatre_id AS cinema_id,
c.name AS cinema_name,
( 3959 * acos( cos( radians('50.4521013') ) *
cos( radians( latitude ) ) *
cos( radians( longitude ) -
radians('-3.5247389') ) +
sin( radians('50.4521013') ) *
sin( radians( latitude ) ) )
) AS distance
FROM google_cinemas c, app_users u
WHERE u.id = 126
HAVING distance < u.range
ORDER BY distance
alternatively you can use it as a sub query which could be faster since HAVING re-evaluates the entire query.
SELECT *
FROM
( SELECT
c.google_theatre_id AS cinema_id,
c.name AS cinema_name,
( 3959 * acos( cos( radians('50.4521013') ) *
cos( radians( latitude ) ) *
cos( radians( longitude ) -
radians('-3.5247389') ) +
sin( radians('50.4521013') ) *
sin( radians( latitude ) ) )
) AS distance,
u.range
FROM google_cinemas c, app_users u
WHERE u.id = 126
ORDER BY distance
)t
WHERE distance < range

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.

combine 2 select queries in mysql

I have 2 select statements:
timestamp of emp getting awards for specific emp id
SELECT * FROM user_table,employeetable,awards where user_table.empid=employeetable.empid AND user_table.empid=awards.empid AND user_table.empid=123 ORDER BY timestamp DESC
All employees staying around 25 miles from the current loc:current location: lat =37 lng=-122
SELECT * ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) )+ sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM user_table,employeetable,awards where user_table.empid=employeetable.empid AND user_table.empid=awards.empid HAVING distance < 25 ORDER BY distance;
How do I combine both and ORDER BY timestamp ?btw both have field timestamp.
1.has specific user
2.all users within specific radius
I really appreciate any help.Thanks in Advance.
You can combine the two queries into a single query, just using logic in the where clause (which this has turned into a having clause:
select *, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) )+ sin( radians(37) ) * sin( radians( lat ) ) ) ) as distance
from user u join
employee e
on u.empid = e.empid join
awards a
on u.empid = a.empid
having empid = 123 or distance < 25;
This uses having instead of where so the distance column alias can be used instead of the formula.

Getting latitude and longitude from a postcode table (MySql) and joining to another table

I have a charities table with fields: charity, postcode
and a postcodes table with fields: postcode, lat, lng
I want to POST a postcode from a web page and find the nearest charities
I'm something of a mysql beginner so I'm a bit lost, but I've been trying various ideas with joins and sub queries none of which work (I either get syntax errors or 'Operand should contain 1 column' with variations on the code below) I've got
Select charity,postcode,
(
(Select lat as lat2, lng as lng2
from postcodes
where postcode='WN8'
)
3959 * acos( cos( radians(lat2) ) * cos( radians( lat ) ) *
cos( radians( lng ) - radians(lng2) ) +
sin( radians(lat2) ) * sin( radians( lat ) ) )
)
AS distance
FROM postcodes
JOIN Charities on charities.postcode=postcodes.postcode
HAVING distance < 30 ORDER BY distance LIMIT 0 , 30;
I've seen lots of examples on here where lat2 and lng2 are obtained from posted values but not from a table in the db.
p.s 'where postcode='WN8' in the example is just for testing
Not sure what error you are getting with the above SQL.
However try this minor tweak and let us know what errors you get
SELECT charity, postcode,
(3959 * acos( cos( radians(CustPostcode.lat) ) * cos( radians( postcodes.lat ) ) *
cos( radians( postcodes.lng ) - radians(CustPostcode.lng) ) +
sin( radians(CustPostcode.lat) ) * sin( radians( postcodes.lat ) ) )
) AS distance
FROM postcodes
INNER JOIN Charities ON charities.postcode=postcodes.postcode
CROSS JOIN (SELECT lat, lng FROM postcodes WHERE postcode='WN8') CustPostcode
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 30;
If you want to know the nearest 30 postcodes and the distances from each charity then something like this would do the job (not tested so excuse any typos).
SELECT charity, Charities.postcode, Postcodes.postcode, PostcodeDistance.distance
FROM Charities
CROSS JOIN Postcodes
INNER JOIN (SELECT PC1.postcode AS postcode1, PC2.postcode AS postcode2, (3959 * acos( cos( radians(PC1.lat) ) * cos( radians( PC2.lat ) ) *
cos( radians( PC2.lng ) - radians(PC1.lng) ) +
sin( radians(PC1.lat) ) * sin( radians( PC2.lat ) ) )
) AS distance
FROM postcodes PC1
CROSS JOIN postcodes PC2) PostcodeDistance
ON Charities.postcode = PostcodeDistance.postcode1
AND Postcodes.postcode = PostcodeDistance.postcode2
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 30;
This should find you the charities within 30 miles
SELECT charity, Charities.postcode, PostcodeDistance.distance
FROM Charities
INNER JOIN (
SELECT PC2.postcode AS postcode2, (3959 * acos( cos( radians(PC1.lat) ) * cos( radians( PC2.lat ) ) *
cos( radians( PC2.lng ) - radians(PC1.lng) ) +
sin( radians(PC1.lat) ) * sin( radians( PC2.lat ) ) )
) AS distance
FROM postcodes PC1
CROSS JOIN postcodes PC2
WHERE PC1.postcode='WN8'
) PostcodeDistance
ON Charities.postcode = PostcodeDistance.postcode2
WHERE PostcodeDistance.distance < 30
ORDER BY PostcodeDistance.distance
LIMIT 0 , 30;

MySQL: Combining two queries into one row result

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;