Сумма до определенной точки из каждой группы - mysql - PullRequest
2 голосов
/ 03 сентября 2010

У меня есть таблица MySQL, содержащая около 1000 строк, заполненных различными типами фруктовых деревьев и их расположением на ферме. Данные выглядят так:

Расположение фруктовых деревьев на ферме

  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

Фруктовые деревья MySQL Table

 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

Теперь я собираюсь запросить эту таблицу, чтобы получить ближайшие "3" дерева каждого типа из центра X (5,3).

Результат запроса должен возвращать что-то вроде:

 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

Может быть несколько деревьев с одинаковым расстоянием от центра, но это не должно иметь значения, потому что как только будет найдено максимальное количество ближайших деревьев (3), мы не будем больше включать деревья из этого типа деревьев. Надеюсь, что это имеет смысл.

Чтобы получить расстояние от центра X до ближайшего дерева, я использую следующую формулу:

Distance = SQRT( POW(ABS(5 - X),2) + POW(ABS(3 - Y),2) )

Вот ссылка, которую я пытался использовать: Сумма до определенной точки - MySql

Как бы я написал MySQL-запрос, чтобы получить результаты? Возможно, мне придется написать несколько запросов для этого, но я просто не уверен, как все это структурировать.

Спасибо

Ответы [ 2 ]

1 голос
/ 03 сентября 2010

Вы можете смоделировать нумерацию строк с помощью переменных .

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

Кажется, работает для меня, но я ожидаю, что производительность будет неуклюжей.

1 голос
/ 03 сентября 2010

Может быть, это?

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
)

РЕДАКТИРОВАТЬ: Лучше попробуйте это:

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
)

На данный момент у меня нет MySQL, поэтому я не могу проверить этот запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...