select two values and the two values with which former values have minimum distance with

不想你离开。 提交于 2019-12-24 12:53:50

问题


I have three columns

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

My expected output is:

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 

what can be the simplest sql query to have the expected output? Note that both the values x1,y1 are considered while finding out the closest pair


回答1:


A possible solution for your use case would to self-join the table using a NOT EXIST clause to ensure that the record being joined is the closest possible record to the current record.

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;

Notes :

  • I renamed the table fields to k(ey), x and y for more readbility.
  • As suggested by you, this uses Euclidian formula to compute the distance : abs(x2-x1) + abs(y2-y1)
  • Please note that, if several records are smallest and equidistant, multiple rows will be returned.

View on DB 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        |



回答2:


I think that in line 4 of your expected result the closest values are wrong.
It should be:

4   100 40  43  40

at least this is the result I get by this:

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

Results:

| 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         |


来源:https://stackoverflow.com/questions/54389523/select-two-values-and-the-two-values-with-which-former-values-have-minimum-dista

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!