MySQL query to retrieve data from table and a 2nd query to pull other results, without duplicates

StackOverflow https://stackoverflow.com/questions/12586423

  •  03-07-2021
  •  | 
  •  

Question

I have been hunting around for a while now on this, but nothing is really coming up that does exactly what i need.

I am searching a table that contains entries with longitude and latitude values. This will return a set of results. There are also entries that don't have long/lat values that I need to return based on some date values.

I know that the two generally wont produce duplicate results, but I am interested nonetheless to know how to do this kind of query.

Q1:

"SELECT id, from_date, to_date, event_title, event_longitude, event_latitude, 
(SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) + 
POW( 69.1 * ( -0.195226 - event_longitude ) * COS( event_latitude / 57.3 ) , 2 ) ) 
* 1609.344) AS distance, (SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) 
+ POW( 69.1 * ( -0.195226 - event_longitude ) * COS( event_latitude / 57.3 ) , 2 ) ) 
* 1609.344) AS true_distance FROM table1 WHERE id!=0 AND no_place='0' 
AND from_date >= '45645646' AND to_date <= '76647446' HAVING distance <= '5000' 
ORDER BY distance ASC LIMIT 50"

this will return the entries matching the long/lat range and ignores any entry marked no_place=0. This uses Haversine to do the long/lat calcs.

the second query needs to pull the entries that have no long/lat but match the date range:

Q2:

"SELECT id, from_date, to_date, event_title, event_longitude, event_latitude FROM
table1 WHERE no_place='1' AND from_date >= '45645646' AND to_date <= '76647446' 
LIMIT 50"

I could run two separate queries here, and append "WHERE ids !in(ids,from,q1)"

to the 2nd query, then use PHP to merge the two results, MySQL must have some cunning method to do this; so the question is this:

How can I do this in just one query, and ignore any ids already found in Q1. I know I have the no_place column which in this scenario will guarantee i have no duplicate rows, but assuming I didn't have this column, how would i go about adding the

"WHERE ids !in(ids,from,q1)" 

clause? Also I think I will probably need to order this total result with the no_place=1 entries first, then the no_place=0 entries ordered by their distance value.

phew!


update after great answer from "Hope I Helped"

so this seems to work, but it looses the distance values in the result:

(SELECT id, from_date, to_date, event_title, event_longitude, event_latitude, 
(SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) + POW( 69.1 * 
( -0.195226 - event_longitude ) * COS( event_latitude / 57.3 ) , 2 ) ) * 1609.344) 
AS distance, (SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) + POW( 69.1 
* ( -0.195226 - event_longitude ) * COS( event_latitude / 57.3 ) , 2 ) ) * 1609.344) 
AS true_distance FROM table1 WHERE id!=0 AND no_place='0' 
HAVING distance <= '5000' ORDER BY distance ASC LIMIT 50) UNION(SELECT id, from_date, 
to_date, event_title, event_longitude, event_latitude, 0, 0 FROM table1 WHERE 
no_place='1' LIMIT 50)

this works, but i have no radius limit in the query now...

(SELECT id, from_date, to_date, event_title, event_longitude, event_latitude, 
(SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) + 
POW( 69.1 * ( -0.195226 - event_longitude ) * COS( event_latitude / 57.3 ) , 2 ) ) 
* 1609.344) AS distance, (SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) 
+ POW( 69.1 * ( -0.195226 - event_longitude ) * COS( event_latitude / 57.3 ) , 2 ) ) 
* 1609.344) AS true_distance FROM table1 WHERE id!=0 AND no_place='0' ORDER BY
distance ASC LIMIT 50) UNION(SELECT id, from_date, to_date, event_title, 
event_longitude, event_latitude, 0, 0 FROM table1 WHERE no_place='1' LIMIT 50)

any ideas?

Was it helpful?

Solution

Try:

(SELECT id, from_date, to_date, event_title, event_longitude, event_latitude,
    (SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) +
    POW( 69.1 * ( -0.195226 - event_longitude ) *
    COS( event_latitude / 57.3 ) , 2 ) ) * 1609.344) AS distance,
    (SQRT( POW( 69.1 * ( event_latitude - 51.4999501637 ) , 2 ) +
    POW( 69.1 * ( -0.195226 - event_longitude ) *
    COS( event_latitude / 57.3 ) , 2 ) ) * 1609.344) AS true_distance
    FROM table1
    WHERE id!=0 AND no_place='0' AND from_date >= '45645646' AND
    to_date <= '76647446'
    HAVING distance <= '5000'
    ORDER BY distance ASC 
    LIMIT 50)
        UNION
    (SELECT id, from_date, to_date, event_title, event_longitude, event_latitude,
    0, 0
    FROM table1
    WHERE no_place='1' AND from_date >= '45645646' AND to_date <= '76647446'
    LIMIT 50)

By applying a UNION, you're able to retrieve the results from both sets, without duplicates.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top