Mysql group by conflict records with order by - mysql

A table contains multiple addresses (latitude and longitude) of a dealers but I want to get nearest dealers
Here is query which return works fine with order by and where dealer=1 of a single dealer but I need multiple unique dealers.
check query and first image result
SELECT
*, ROUND(
(
3959 * ACOS(
COS(RADIANS(41.355724)) * COS(
RADIANS(adzip.dealer_zipcode_latitude)
) * COS(
RADIANS(adzip.dealer_zipcode_longitude) - RADIANS(- 87.607332)
) + SIN(RADIANS(41.355724)) * SIN(
RADIANS(adzip.dealer_zipcode_latitude)
)
)
), 2
) AS dealer_distance
FROM
ad_dealers_zipcodes AS adzip
WHERE adzip.dealer_zipcode_dealer_id = 1 #GROUP BY adzip.dealer_zipcode_dealer_id
ORDER BY dealer_distance ASC
when I add group by adzip.dealer_zipcode_dealer_id query returns 4th record but I need the 1st record of result which dealer_distance is 13.80

Actually, I think you should add a level to your query for the group by statement to work as you intend, like this:
SELECT *, min(dealer_distance) AS min_dealer_distance FROM
(
SELECT
*, ROUND(
(
3959 * ACOS(
COS(RADIANS(41.355724)) * COS(
RADIANS(adzip.dealer_zipcode_latitude)
) * COS(
RADIANS(adzip.dealer_zipcode_longitude) - RADIANS(- 87.607332)
) + SIN(RADIANS(41.355724)) * SIN(
RADIANS(adzip.dealer_zipcode_latitude)
)
)
), 2
) AS dealer_distance
FROM
ad_dealers_zipcodes AS adzip
WHERE adzip.dealer_zipcode_dealer_id = 1 #GROUP BY adzip.dealer_zipcode_dealer_id
ORDER BY dealer_distance ASC
) as t1
GROUP BY dealer_zipcode_dealer_id
ORDER BY min_dealer_distance ASC

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

Calculating Distance on Combined Table

I have the following SQL statement:
SELECT Distinct(Venue_Name), Count(*) as `num1`
FROM venuetagview
INNER JOIN
(
SELECT Tag,COUNT(*) AS `num`
FROM usertags
WHERE UserID=4
GROUP BY Tag
ORDER BY `num` DESC
) as a
ON venuetagview.Tag=a.Tag
GROUP BY Venue_Name
ORDER BY `num1` DESC
And I am trying to add a 'distance' calculation into it, using the latitude/longitude I have in the venuetagview table. I have tried this:
SELECT
( 6371
* acos( cos( radians(51.529099) )
* cos( radians( Venue_Latitude ) )
* cos( radians( Venue_Longitude )
- radians(-0.084981) )
+ sin( radians(51.529099) )
* sin( radians( Venue_Latitude ) ) ) ) AS distance,
Distinct(Venue_Name),
Count(*) as `num1`
FROM venuetagview
INNER JOIN
(
SELECT Tag,
COUNT(*) AS `num`
FROM usertags
WHERE UserID=4
GROUP BY Tag
ORDER BY `num` DESC
) as a
ON venuetagview.Tag=a.Tag
GROUP BY Venue_Name
ORDER BY `num1` DESC
However I am getting an error using this.
Only issue I see with your posted query is
distinct is keywork and should be used like distinct column_name
SELECT Distinct (Venue_Name) should just be SELECT Venue_Name or
SELECT Distinct Venue_Name
As mentioned by Strawberry removing DISTINCT solved this:
SELECT
( 6371 * acos( cos( radians(51.529099) )
* cos( radians( Venue_Latitude ) )
* cos( radians( Venue_Longitude )
- radians(-0.084981) )
+ sin( radians(51.529099) )
* sin( radians( Venue_Latitude ) ) ) ) AS distance,
Venue_Name,
Count(*) asnum1
FROM venuetagview
INNER JOIN
(
SELECT Tag,
COUNT(*) ASnum
FROM usertags
WHERE UserID=4
GROUP BY Tag
ORDER BYnumDESC) as a
ON venuetagview.Tag=a.Tag
GROUP BY Venue_Name
ORDER BY distance ASC

MySQL join multiple tables?

I have 3 tables
tblMarkers
tblReviews
tblImages
I want to return ALL the records from tblMarkers and a count of all the reviews and images for each marker.
To complicate it further it should return all the markers within a radius of a known point.
so the expected result would be
MarkerID-MarkerName-ReviewCount-ImageCount
1223-SomeName-0-1
This is what I have so far and this returns a count of reviews, but I cant get the right SQL to add the count of images
SELECT
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`,
(3959 * acos( cos( radians('45.1') ) * cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians('6') ) + sin( radians('45.1') ) * sin( radians( Latitude ) ) ) )
AS distance,
Count(`tblReviews`.`marker_id`) As reviewCount
FROM
`tblMarkers`
LEFT JOIN `tblReviews` ON `tblMarkers`.`ID` = `tblReviews`.`marker_id`
GROUP BY
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`
HAVING
`distance` < '50'
ORDER BY
distance;
The Images table structure is
ID [primaryKey] (same as tblMarkers.ID)
file
title
How do I add a count of all the images?
Try this:
SELECT M.ID
, M.Type
, M.Name
, M.Latitude
, M.Longitude
, (3959 * acos(cos(radians('45.1')) * cos(radians(M.Latitude )) * cos(radians(M.Longitude) - radians('6')) + sin(radians('45.1')) * sin(radians(M.Latitude )))) AS distance
, IFNULL(COUNT(DISTINCT R.review_id) , 0) AS ReviewCount
, IFNULL(COUNT(DISTINCT I.ID), 0) AS ImageCount
FROM tblMarkers AS M
LEFT JOIN tblReviews AS R ON R.marker_id = M.ID
LEFT JOIN tblImages AS I ON I.marker_id = M.ID
GROUP BY M.ID, M.Type, M.Name, M.Latitude, M.Longitude
HAVING distance < 50
ORDER BY distance
I bet you already know LEFT JOIN. So I used COUNT(DISTINCT R.review_id)) to count all distinct review id's (just make sure that review_id is unique). In case there are no corresponding review and image record for a specific marker record, I used IFNULL(XXX , 0) to display 0.
I used ALIASES to make your query clean and neat. Feel free to ask.
IF ID field of image table is the reference of marker table ID field then the query will be:
SELECT
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`,
(3959 * acos( cos( radians('45.1') ) * cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians('6') ) + sin( radians('45.1') ) * sin( radians( Latitude ) ) ) )
AS distance,
Count(`tblReviews`.`marker_id`) As reviewCount,
Count(`tblImage`.`ID`) As imageCount,
FROM
`tblMarkers`
LEFT JOIN `tblReviews` ON `tblMarkers`.`ID` = `tblReviews`.`marker_id`
LEFT JOIN `tblImage` ON `tblMarkers`.`ID` = `tblImages`.`ID`
GROUP BY
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`
HAVING
`distance` < '50'
ORDER BY
distance;