MySQL Select statement with datetime - mysql

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'

Related

Find a partial match in MySQL query with multiple "OR"

I need to find partial or full matches in a MySQL query. I am performing queries in multiple tables using 'OR' and need to know whether all conditions have been met or just some of them.
I believe the easiest way to do this would be to create a new column called 'partial' which would either be 0 or 1 (Feel free to correct me if I am wrong).
Here is my query:
SELECT
id, confirmed, name, addressLine1, addressLine2, addressCity, addressPostcode,
addressLat, addressLon,
(6371 * acos( cos( radians( '53.649779' ) )
* cos( radians( addressLat ) )
* cos( radians( addressLon ) - radians( '-1.6026266' ) )
+ sin( radians( '53.649779' ) ) * sin( radians( addressLat ) ) )
) distance
FROM TABLE_NAME
WHERE active = '1'
AND deleted = '0'
AND
(
id < 0
OR
id IN
(
SELECT establishmentID
FROM appEstablishmentDrinks
WHERE active = '1'
AND deleted = '0'
AND manufacturerDrinkID IN (101)
GROUP BY establishmentID
HAVING count(distinct manufacturerDrinkID) = 1
)
OR
id IN
(
SELECT establishmentID
FROM appEstablishmentFacilities
WHERE active = '1'
AND deleted = '0'
AND facilityID IN (37)
)
)
HAVING distance < '15'
In MySQL true = 1 and false = 0. So simply add conditions: (id < 0) + (id in (...)) + (id in (...)) and check whether you got all three matches or less.
SELECT
id, confirmed, name, addressLine1, addressLine2, addressCity, addressPostcode,
addressLat, addressLon, distance,
case when count_matches = 3 then 'full' else 'partial' end as matching
FROM
(
SELECT
id, confirmed, name, addressLine1, addressLine2, addressCity, addressPostcode,
addressLat, addressLon,
(6371 * acos( cos( radians( 53.649779 ) )
* cos( radians( addressLat ) )
* cos( radians( addressLon ) - radians( -1.6026266 ) )
+ sin( radians( 53.649779 ) ) * sin( radians( addressLat ) ) )
) as distance,
(id < 0 )
+
(
id IN
(
SELECT establishmentID
FROM appEstablishmentDrinks
WHERE active = 1
AND deleted = 0
AND manufacturerDrinkID IN (101)
GROUP BY establishmentID
HAVING count(distinct manufacturerDrinkID) = 1
)
)
+
(
id IN
(
SELECT establishmentID
FROM appEstablishmentFacilities
WHERE active = 1
AND deleted = 0
AND facilityID IN (37)
)
) as count_matches
FROM TABLE_NAME
WHERE active = 1
AND deleted = 0
) x
WHERE distance < 15
AND count_matches > 0;

having clause in mysql query error

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

Converting 'WITH CTE' MSSQL to MySQL

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;

Mysql select from inner select with join

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

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