Reputation: 708
I have a MySQL table with about 1000 rows, filled with different types of fruit trees and their locations on a farm. The data looks like this:
7 |
6 | G G
5 | G
Y 4 | G G
3 | A X G G
2 | A A A
1 |_ _ _ _ _ _ _
1 2 3 4 5 6 7
X
ID Type X Y
-- ---- -- --
1 Apple 3 2
2 Grape 3 4
3 Grape 3 5
4 Grape 3 6
5 Apple 4 2
6 Apple 4 3
7 Grape 4 6
8 Apple 5 2
9 Grape 5 4
10 Grape 6 3
11 Grape 7 3
Now, I am looking to query this table to get the nearest "3" trees only of each type from the center X (5,3).
The query result should return something like:
ID Type X Y
-- ---- -- --
6 Apple 4 3
5 Apple 4 2
8 Apple 5 2
9 Grape 5 4
10 Grape 6 3
11 Grape 7 3
There may be several trees with the same distance from the center but that should not matter because once the maximum number of nearest trees (3) is meet then we wouldn't include anymore trees from that type of tree. Hope this makes sense.
To get the distance from the center X to a nearby tree I use the below formula:
Distance = SQRT( POW(ABS(5 - X),2) + POW(ABS(3 - Y),2) )
Here is a reference that I have been trying to use: Sum until certain point - MySql
How would I write a MySQL query to get the results? I may have to write several queries to do this but am just unsure how to structure it all.
Thank you
Upvotes: 2
Views: 291
Reputation: 78105
You can simulate row numbering with variables.
SELECT @i:=0, @type:=''
;
SELECT
id, type, x, y
FROM (
SELECT
id, type, x, y
, SQRT( POW(ABS(5 - x),2) + POW(ABS(3 - y),2) ) AS distance
, IF( type=@type, @i:=@i+1, @i:=0 ) AS rank
, IF( type=@type, @type, @type:=type ) AS new_type
FROM
fruit_trees
ORDER BY
type
, distance
) x
WHERE
rank < 3
Seems to work for me, but I expect performance will be ropey.
Upvotes: 1
Reputation: 22504
Maybe this?
select id, type, x, y
from fruit_trees as ft1
where not exists (
select null
from fruit_trees as ft2
where
ft2.type = ft1.type and
ft2.distance <= ft1.distance
limit 3, 1
)
EDIT: Better try this:
select id, type, x, y
from fruit_trees as ft1
where id in (
select id
from fruit_trees as ft2
where
ft2.type = ft1.type
order by ft2.distance
limit 3
)
I have no MySQL available at the moment so i cannot test that query.
Upvotes: 1