выберите два значения и два значения, с которыми предыдущие значения имеют минимальное расстояние с - PullRequest
0 голосов
/ 27 января 2019

У меня есть три столбца

Key, x1,  y1
1    31   34
2    43   40
3    41   44
4    100  40

Мой ожидаемый результат:

Key, x1,  y2, closest_x1,  closest_y2
1    31   34     43          40
2    43   40     41          44
3    41   44     43          40
4    100  40     41          44 

Какой самый простой SQL-запрос может иметь ожидаемый результат?Обратите внимание, что оба значения x1, y1 учитываются при поиске ближайшей пары

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Возможным решением для вашего варианта использования было бы самостоятельное присоединение к таблице с помощью предложения NOT EXIST, чтобы гарантировать, что присоединяемая запись является ближайшей возможной записью к текущей записи.

SELECT t1.*, t2.x closest_x, t2.y closest_y
FROM mytable t1
INNER JOIN mytable t2
    ON t2.k <> t1.k
    AND NOT EXISTS (
        SELECT 1
        FROM mytable t3
        WHERE
            t3.k <> t1.k
            AND abs(t1.x - t3.x) + abs(t1.y - t3.y) < abs(t1.x - t2.x) + abs(t1.y - t2.y)  
    )
ORDER BY 1;

Примечания:

  • Я переименовал поля таблицы в k (эй), x и y для большей читаемости.
  • Как вы предполагаете, здесь используется евклидова формула длявычислите расстояние: abs(x2-x1) + abs(y2-y1)
  • Обратите внимание, что если несколько записей наименьшее и равноудалено, будет возвращено несколько строк.

Вид на БД Fiddle :

SELECT t1.*, t2.x closest_x, t2.y closest_y
FROM mytable t1
INNER JOIN mytable t2
    ON t2.k <> t1.k
    AND NOT EXISTS (
        SELECT 1
        FROM mytable t3
        WHERE
            t3.k <> t1.k
            AND abs(t1.x - t3.x) + abs(t1.y - t3.y) < abs(t1.x - t2.x) + abs(t1.y - t2.y)  
    )
ORDER BY 1;
| k   | x   | y   | closest_x | closest_y |
| --- | --- | --- | --------- | --------- |
| 1   | 31  | 34  | 43        | 40        |
| 2   | 43  | 40  | 41        | 44        |
| 3   | 41  | 44  | 43        | 40        |
| 4   | 100 | 40  | 43        | 40        |
0 голосов
/ 27 января 2019

Я думаю, что в строке 4 вашего ожидаемого результата ближайшие значения неверны.Это должно быть:

4   100 40  43  40

по крайней мере это результат, который я получаю следующим образом:

select t.*, tt.x1 closest_x1, tt.y1 closest_y1
from tablename t
inner join tablename tt
on tt.key = (
  select min(key) from tablename where power(x1 - t.x1, 2) + power(y1 - t.y1, 2) = (
    select min(power(x1 - t.x1, 2) + power(y1 - t.y1, 2)) from tablename where key <> t.key
  )
)
order by t.key

Результаты:

| key  | x1  | y1  | closest_x1 | closest_y1 |
| ---- | --- | --- | ---------- | ---------- |
| 1    | 31  | 34  | 43         | 40         |
| 2    | 43  | 40  | 41         | 44         |
| 3    | 41  | 44  | 43         | 40         |
| 4    | 100 | 40  | 43         | 40         |
...