Mysql select from inner select with join - mysql

Can I do something like this ? Bassically I user inner select to select lowest date that is bigger than NOW(), for example 9.4.2014 would mathc this, for each event ids. And now I would like to return this, here is the code :
SELECT id_event , event_title, event_details, dates.event_date, id_show, id_category, distance FROM(
SELECT event.id_event id_event, event_title, event_details, min(event_date_time) event_date_time, event_showtime.id_show , event_category.id_category id_category, ( 6371 * ACOS( COS( RADIANS( '49.20513921227407' ) ) * COS( RADIANS( event_showtime.latitude ) ) * COS( RADIANS( event_showtime.longitude ) - RADIANS( '18.762441839599678' ) ) + SIN( RADIANS( '49.20513921227407' ) ) * SIN( RADIANS( event_showtime.latitude ) ) ) ) AS distance
FROM event
JOIN event_showtime ON event.id_event = event_showtime.id_event
JOIN event_category ON event.id_category = event_category.id_category
JOIN ( SELECT id_event, min(event_date_time) as event_date_time FROM event_showtime
WHERE event_date_time > NOW()
GROUP BY id_event ) AS dates ON event.id_event = dates.id_event
WHERE event_date_time > NOW()
GROUP BY event.id_event
HAVING distance < '5'
ORDER BY distance
LIMIT 0 , 20
)t
Here is the SQLfiddle http://www.sqlfiddle.com/#!2/6545ab/51 with 3 tables :)
How could I access those inner details in the top select ?

You need to give the table aliases to your columns if there are multiple columns that have same names
SELECT
es.id_show,
e.id_event ,
e.event_title,
e.event_details,
d.event_date_time,
ec.id_category,
( 6371 * ACOS( COS( RADIANS( '49.20513921227407' ) ) * COS( RADIANS( es.latitude ) ) * COS( RADIANS( es.longitude ) - RADIANS( '18.762441839599678' ) ) + SIN( RADIANS( '49.20513921227407' ) ) * SIN( RADIANS( es.latitude ) ) ) ) AS distance
FROM event e
JOIN event_showtime es ON e.id_event = es.id_event
JOIN event_category ec ON e.id_category = ec.id_category
JOIN ( SELECT id_event,
min(event_date_time) as event_date_time
FROM event_showtime
WHERE event_date_time > NOW()
GROUP BY id_event ) AS d
ON (es.id_event = d.id_event AND es.event_date_time =d.event_date_time)
WHERE d.event_date_time > NOW()
GROUP BY e.id_event
-- HAVING distance < '5'
ORDER BY distance
LIMIT 0 , 20
Here is the simplified version of your query you are using HAVING clause to check the distance should be less than 5 but for second event the distance is 112.773868864733 in my query i have commented the having clause just to show your the results,second thing you asked for the nearest date to NOW() but not include past dates so in your provided sample data set for event_showtime
`id_show`, `id_event`, `latitude`, `longitude`, `event_date_time`
(1, 1, 49.2016762922894, 18.7615620750428, '2014-03-31 16:13:17'),
(2, 1, 49.2016762922894, 18.7615620750428, '2014-04-01 20:00:00'),
(3, 2, 49.2113914818564, 18.7520992416382, '2014-03-31 15:00:00'),
(4, 2, 49.0545135142313, 20.2952223676682, '2014-04-16 11:00:00'),
(5, 2, 49.2113914818564, 18.7520992416382, '2014-04-23 11:00:00'),
(6, 2, 49.0545135142313, 20.2952223676682, '2014-04-30 11:00:00'),
(7, 2, 49.2016762922894, 18.7615620750428, '2014-04-29 12:00:00'),
(8, 1, 49.2016762922894, 18.7615620750428, '2014-04-24 12:00:00');
For event id 1 there are 3 datetimes 2014-03-31 16:13:17 ,2014-04-01 20:00:00,2014-04-24 12:00:00 the date 2014-04-24 12:00:00 is the nearest one for event id 2 the date 2014-04-16 11:00:00 is the nearest one not 23rd one ,third thing you asked in comments that id_show is wrong for this your last join from subquery needs another condition with event_date_time to be joined to get the exact id you need
Hope it makes sense
Fiddle Demo
For your specific requirement to select nearest dates with distance limitation you can do so
SELECT t.* FROM (
SELECT
es.id_show,
e.id_event,
e.event_title,
e.event_details,
MIN(es.event_date_time) event_date_time,
ec.id_category,
es.distance
FROM
event e
JOIN event_category ec
ON e.id_category = ec.id_category
JOIN
(SELECT
`id_show`,
`id_event`,
`latitude`,
`longitude`,
event_date_time,
(
6371 * ACOS(
COS(RADIANS('49.20513921227407')) * COS(RADIANS(event_showtime.latitude)) * COS(
RADIANS(event_showtime.longitude) - RADIANS('18.762441839599678')
) + SIN(RADIANS('49.20513921227407')) * SIN(RADIANS(event_showtime.latitude))
)
) AS distance
FROM
event_showtime
WHERE `event_date_time` > NOW()
HAVING distance < 5) es
ON (e.id_event = es.id_event)
GROUP BY e.id_event
) t
JOIN `event_showtime` es USING(id_event,event_date_time)
ORDER BY t.distance
LIMIT 0, 20
Fiddle Demo

Related

MySQL: How can I calculate the median in a specific radius (longitude / latitude)

I want to calculate the median and average for given coordinates in a specific radius.
The important attributes are:
- latitude
- longitude
- price
The sql command to calculate the average is:
SELECT avg(price) as average
FROM (SELECT r.*,
( 6371 * acos( cos( radians(37.3541079) ) * cos( radians( ANY_VALUE(`latitude` )) ) * cos( radians( ANY_VALUE(`longitude`) ) - radians(-121.9552356) ) + sin( radians(37.3541079) ) * sin( radians( ANY_VALUE(`latitude`) ) ) ) ) AS distance
FROM `Rental` r
) r
WHERE distance <= 20;
My question is how can I calculate the median for the price in the given coordinates and radius. MySQL has no median() function.
EDIT:
Now I have tried the code from Simple way to calculate median with MySQL
SELECT AVG(middle_values) AS 'median' FROM (
SELECT t1.price AS 'middle_values' FROM
(
SELECT #row:=#row+1 as `row`, x.price
FROM rental AS x, (SELECT #row:=0) AS r
WHERE 1
-- put some where clause here
ORDER BY x.price
) AS t1,
(
SELECT COUNT(*) as 'count'
FROM rental x
WHERE 1
-- put same where clause here
) AS t2
-- the following condition will return 1 record for odd number sets, or 2 records for even number sets.
WHERE t1.row >= t2.count/2 and t1.row <= ((t2.count/2) +1)) AS t3;
It works for all the 200'000 records, but when I will add the WHERE distance <= 20 is the mysql - request overloaded.
SELECT AVG(middle_values) AS 'median' FROM (
SELECT t1.price AS 'middle_values' FROM
(
SELECT #row:=#row+1 as `row`, x.price
FROM rental AS x, (SELECT #row:=0) AS r, (SELECT a.*,
( 6371 * acos( cos( radians(37.3541079) ) * cos( radians( ANY_VALUE(`latitude` )) ) * cos( radians( ANY_VALUE(`longitude`) ) - radians(-121.9552356) ) + sin( radians(37.3541079) ) * sin( radians( ANY_VALUE(`latitude`) ) ) ) ) AS distance
FROM `Rental` a
) a
WHERE distance <= 20
-- put some where clause here
ORDER BY x.price
) AS t1,
(
SELECT COUNT(*) as 'count'
FROM rental x, (SELECT a.*,
( 6371 * acos( cos( radians(37.3541079) ) * cos( radians( ANY_VALUE(`latitude` )) ) * cos( radians( ANY_VALUE(`longitude`) ) - radians(-121.9552356) ) + sin( radians(37.3541079) ) * sin( radians( ANY_VALUE(`latitude`) ) ) ) ) AS distance
FROM `Rental` a
) a
WHERE distance <= 20
-- put same where clause here
) AS t2
-- the following condition will return 1 record for odd number sets, or 2 records for even number sets.
WHERE t1.row >= t2.count/2 and t1.row <= ((t2.count/2) +1)) AS t3;
Is there somewhere a misstep?
The problem is with the table scan to compute the distances, not with the median.
Put the data in a TEMPORARY TABLE so you don't have to evaluate it 3 times (avg, count, and median).
Add a "bounding box" to the innermost WHERE to limit the checks to a 20x20 "square".
INDEX(latitude)
Use HAVING distance < 20 instead of needing yet-another subquery.

Query to get nearest distance record

I have following mysql query:
SELECT a.id
, ( 3959 * acos( cos( radians(a.latitude) ) * cos( radians( w.latitude ) )
* cos( radians( w.longitude ) - radians(-a.longitude) )
+ sin( radians(a.latitude) ) * sin(radians(w.latitude)) ) ) distance
FROM global_restaurants a
JOIN webgeocities w
ON w.name = a.locality
AND w.country_code = a.country
AND a.latitude LIKE w.latitude
JOIN states s
ON s.state_code = w.state_code
AND w.country_code = s.country_code
WHERE a.city_id = 0
After execution it returns:
id distance
70 6665.478678743614
70 6496.46971480875
70 6725.900646648246
70 6733.5156930808
90 6969.449661399672
90 7252.889875588891
I want it to only return 2 rows with minimum distance like:
id distance
70 6496.46971480875
90 6969.449661399672
add order by at the end of your query:
order by distance ASC LIMIT 2;
now you calculating the distance but
at end of the query you must sort them and limit the returns row count..
.
NOTE:
i think you have a small mistake on your query
the 3959 is for miles but i think the values are in meter
your full query can be like this:
select a.id, ( 6371000 * acos( cos( radians(a.latitude) ) * cos( radians( w.latitude ) )
* cos( radians( w.longitude ) - radians(-a.longitude) ) + sin( radians(a.latitude) ) * sin(radians(w.latitude)) ) ) AS distance
from `global_restaurants` as a INNER JOIN webgeocities as w ON (w.name = a.locality AND w.country_code = a.country and a.latitude like w.latitude) INNER JOIN
states AS s ON (s.state_code = w.state_code and w.country_code = s.country_code) where a.city_id = '0' ORDER BY distance ASC LIMIT 2;
For simplicity, let's assumed that you have your query in view - stack, then your query should look like this
select stack.* from stack join (
SELECT id, GROUP_CONCAT(distance ORDER BY
distance asc) grouped_distance FROM stack GROUP BY id
) group_distance on group_distance.id=stack.id
where find_in_set(stack.distance,group_distance.grouped_distance)between 1 and 2;

How to get minimum radius location

I have 2 tables
1. feeds => id,name
2. feed_locations => id, feed_id, latitude,longitude,location_name
A feed have multiple locations.
now i want to search near by feed from user current location
I require user latitude or longitude so i fetch from google location and radius
Now i use this mysql query
SELECT
`Feed`.`id`,
`Feed`.`name`,
(3959 * acos (cos ( radians(40.7127837) ) * cos( radians( FeedLocation.latitude ) ) * cos( radians( FeedLocation.longitude ) - radians(-74.00594130000002) ) + sin ( radians(40.7127837) ) * sin( radians( FeedLocation.latitude )))) AS `distance`,
(Select COUNT(id) FROM feed_locations WHERE feed_id = `Feed`.`id`) AS `location_count` FROM `feeds` AS `Feed`
LEFT JOIN `feed_locations` AS `FeedLocation` ON (`FeedLocation`.`feed_id` = `Feed`.`id`)
GROUP BY `Feed`.`id` HAVING distance < 10
ORDER BY `distance` ASC
This query giving me result but
i require minimum distance of the feed_locations from user current location. Distance field give me highest value but i require lowest value from feed_locations table.
My query is working but issue it that :
Like if a single feed have 10 location lik 1m,2m,3m,4m,5m,10m,100m distance. and i want to find 5m distance all feed then it works but it shows me that this feed have 5m. distance from me but result should be 1m distance.
I have created a Fiddle please check http://sqlfiddle.com/#!9/c408e6/5
According to the fiddle in table 1 result is coming that feed1 is 4.02m from my current location but this feed have 2 location in table2 i have show each of location distance .so feed1 one of location is zero mile distance from me but it give result that feed1 is 4.02mile
SELECT
a.id,
a.name,
a.distance,
a.location_count
FROM
(SELECT
`Feed`.`id`,
`Feed`.`name`,
(3959 * acos (cos ( radians(40.7127837) ) *
cos( radians( FeedLocation.latitude ) ) *
cos( radians( FeedLocation.longitude ) -
radians(-74.00594130000002) ) + sin ( radians(40.7127837) ) *
sin( radians( FeedLocation.latitude )))) AS `distance`,
(Select COUNT(id)
FROM feed_locations
WHERE feed_id = `Feed`.`id`) AS `location_count`
FROM `feeds` AS `Feed`
LEFT JOIN `feed_locations` AS `FeedLocation` ON (`FeedLocation`.`feed_id` = `Feed`.`id`)
ORDER BY `distance` ASC) AS a
GROUP BY a.id HAVING distance < 10;
In the fiddle I worked out this query you see and it works, now result is 0. The point is that if you group a not ordered set of records and then you order... you do not order anything. You have to order and then group the ordered set.
Hope it works for you.
Regards

MySQL Select statement with datetime

I have this MySQL SELECT statment that works for me, but I would like to improve it by a bit :
SELECT event.id_event, event_title, event_details, event_date_time, event_showtime.id_show, event_category.id_category, ( 6371 * ACOS( COS( RADIANS( '49.20513921227407' ) ) * COS( RADIANS( event_showtime.latitude ) ) * COS( RADIANS( event_showtime.longitude ) - RADIANS( '18.762441839599678' ) ) + SIN( RADIANS( '49.20513921227407' ) ) * SIN( RADIANS( event_showtime.latitude ) ) ) ) AS distance
FROM event
JOIN event_showtime ON event.id_event = event_showtime.id_event
JOIN event_category ON event.id_category = event_category.id_category
HAVING distance < '5'
ORDER BY distance
LIMIT 0 , 20
This returns a set of 3 rows :
id_event event_title event_details event_date_time id_show id_category distance
1 Testovacia na FRI Testovacia udalosť na FRI 2014-04-01 20:00:00 2 1 0.390327906350887
1 Testovacia na FRI Testovacia udalosť na FRI 2014-03-31 16:13:17 1 1 0.390327917895938
2 Čin-Čin Čin-Čin je nádherný poetický príbeh o dospievaní. ... 2014-03-31 15:00:00 3 2 1.02364018489261
This is basically a set of eventshowtimes in location. But the trick is in the result, I would only like to see one result of event with id = 1 that has the date time most closest to NOW(). Is this possible ?
Edit: this is the content of event_showtime table :
INSERT INTO `event_showtime` (`id_show`, `id_event`, `latitude`, `longitude`, `event_date_time`) VALUES
(1, 1, 49.2016762922894, 18.7615620750428, '2014-03-31 16:13:17'),
(2, 1, 49.2016762922894, 18.7615620750428, '2014-04-01 20:00:00'),
(3, 2, 49.2113914818564, 18.7520992416382, '2014-03-31 15:00:00'),
(4, 2, 49.0545135142313, 20.2952223676682, '2014-04-16 11:00:00'),
(5, 2, 49.2113914818564, 18.7520992416382, '2014-04-23 11:00:00'),
(6, 2, 49.0545135142313, 20.2952223676682, '2014-04-30 11:00:00'),
(7, 2, 49.2016762922894, 18.7615620750428, '2014-04-29 12:00:00'),
(8, 1, 49.2016762922894, 18.7615620750428, '2014-04-24 12:00:00');
Try this:
SELECT id_event , event_title, event_details, event_date_time, id_show, id_category, distance FROM(
SELECT event.id_event id_event, event_title, event_details, max(event_date_time) event_date_time, max(event_showtime.id_show) id_show, event_category.id_category id_category, ( 6371 * ACOS( COS( RADIANS( '49.20513921227407' ) ) * COS( RADIANS( event_showtime.latitude ) ) * COS( RADIANS( event_showtime.longitude ) - RADIANS( '18.762441839599678' ) ) + SIN( RADIANS( '49.20513921227407' ) ) * SIN( RADIANS( event_showtime.latitude ) ) ) ) AS distance
FROM event
JOIN event_showtime ON event.id_event = event_showtime.id_event
JOIN event_category ON event.id_category = event_category.id_category
GROUP BY event.id_event
HAVING distance < '5'
ORDER BY distance
LIMIT 0 , 20
)t
You need to sort them according to event_date_time descending, then add limit 1:
SELECT event.id_event, event_title, event_details, event_date_time, event_showtime.id_show, event_category.id_category, ( 6371 * ACOS( COS( RADIANS( '49.20513921227407' ) ) * COS( RADIANS( event_showtime.latitude ) ) * COS( RADIANS( event_showtime.longitude ) - RADIANS( '18.762441839599678' ) ) + SIN( RADIANS( '49.20513921227407' ) ) * SIN( RADIANS( event_showtime.latitude ) ) ) ) AS distance
FROM event
JOIN event_showtime ON event.id_event = event_showtime.id_event
JOIN event_category ON event.id_category = event_category.id_category
HAVING distance < '5'
ORDER BY event_date_time DESC
LIMIT 1
A few questions though - why would you add order by distance and limit 0,20 if you are only expecting one record? Or do you mean to get only the latest event_date_time for EACH id? If so, you need to get the MAX(event_date_time) and id_event for all records, then join this to you outside table
SELECT event.id_event, event_title, event_details, event_date_time
FROM event
JOIN event_showtime ON event.id_event = event_showtime.id_event
JOIN event_category ON event.id_category = event_category.id_category
JOIN (SELECT MAX(event_date_time) as dt, id_event from event) inner_t
ON inner_t.id_event = event.id_event
AND inner_t.dt = event.event_date_time
WHERE distance < '5'

Sql query combining

i have two sql queries those are following
1) SELECT a.* FROM modzzz_listing_main as a LEFT JOIN modzzz_listing_rating as b ON a.id=b.gal_id WHERE LTRIM(a.city) = 'Houston' AND a.state = 'TX' AND a.tags LIKE '%Barber Shop%' ORDER BY b.gal_rating_sum DESC LIMIT 0 ,10
2) SELECT zip_code ,( 3959 * acos( cos( radians('41.97734070') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('-70.97234344') ) + sin( radians('41.97734070') ) * sin( radians( latitude ) ) ) ) AS distance FROM city_finder WHERE latitude IS NOT NULL AND longitude IS NOT NULL HAVING distance < 20 ORDER BY distance ASC
how can i combine this two queries by the condition `
modzzz_listing_main.zip=city_finder.zip_code
` .i am totally confused..please any one help me..
to see the join easier:
select * from
(
SELECT a.* FROM modzzz_listing_main as a LEFT JOIN modzzz_listing_rating as b ON a.id=b.gal_id WHERE LTRIM(a.city) = 'Houston' AND a.state = 'TX' AND a.tags LIKE '%Barber Shop%' ORDER BY b.gal_rating_sum DESC LIMIT 0 ,10
) queryA
left join
(
SELECT zip_code ,( 3959 * acos( cos( radians('41.97734070') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('-70.97234344') ) + sin( radians('41.97734070') ) * sin( radians( latitude ) ) ) ) AS distance FROM city_finder WHERE latitude IS NOT NULL AND longitude IS NOT NULL HAVING distance < 20 ORDER BY distance ASC
) queryB
on queryA.zip=queryB.zip_code
proper formatting
SELECT *
FROM
( SELECT a.*
FROM modzzz_listing_main AS a
LEFT JOIN modzzz_listing_rating AS b ON a.id=b.gal_id
WHERE LTRIM(a.city) = 'Houston'
AND a.state = 'TX'
AND a.tags LIKE '%Barber Shop%'
ORDER BY b.gal_rating_sum DESC LIMIT 0 ,
10 ) queryA
LEFT JOIN
( SELECT zip_code ,
(3959 * acos(cos(radians('41.97734070')) * cos(radians(latitude)) * cos(radians(longitude) - radians('-70.97234344')) + sin(radians('41.97734070')) * sin(radians(latitude)))) AS distance
FROM city_finder
WHERE latitude IS NOT NULL
AND longitude IS NOT NULL HAVING distance < 20
ORDER BY distance ASC ) queryB ON queryA.zip=queryB.zip_code