我有一个表,其中包含世界地图的分区。分区是通过将所有区域分割成矩形来完成的,称为“平铺”。和往常一样,矩形有左下角和右上角,都由浮点坐标表示。
任务是:
对于每个平铺,将其邻居设置为右侧,将其邻居设置为顶部,就像一组{tile_id, id_of_top_neighbour, id_of_right_n}
地砖A的右邻是指这样的地砖B,它的最小X坐标与A的最大X坐标最接近,而Y是相同的。
表格说明:

integer tile_id; --Tile id. PK.
real    min_x;  --X coordinate of bottom-left point
real    min_y;  --Y coordinate of bottom-left point
real    max_x;  --X coordinate of upper-right point
real    max_y;  --Y coordinate of upper-right point

失败的解决方案:
首先,我尝试按一个坐标排序,在Java端按此结果集迭代,然后对每一行执行额外的选择。表演不够。
现在我想知道一个纯sql解决方案是否可能在运行时更快…
事先感谢任何帮助或想法。
编辑:
两个瓷砖之间可能有间隙,因此(例如,对于右邻居)b.min_x-a.max_x可以大于0。不过,两块瓷砖的相交不能超过边界。
我们正在使用Postgres8.3

最佳答案

窗口函数和CTE将使这非常容易做到。我想这两款都有8.4及以上版本。我强烈建议你升级。我在9.0上测试了这个溶液:

with tile_data as
(
    select
        tile_id,
        min_x,
        min_x + 0.9 as max_x,
        min_y,
        min_y + 0.9 as max_y
    from
    (
     select 1 as tile_id, 0.0 as min_x, 0.0 as min_y union all
     select 2, 1.0, 0.0 union all
     select 3, 2.0, 0.0 union all
     select 4, 0.0, 1.0 union all
     select 5, 1.0, 1.0 union all
     select 6, 2.0, 1.0 union all
     select 7, 0.0, 2.0 union all
     select 8, 1.0, 2.0 union all
     select 9, 2.0, 2.0
    ) a
),
right_neighbor_tiles as
(
    select
        tile_id,
        other_tile_id as right_neighbor_tile_id
    from
    (
        select
             a.tile_id,
             b.tile_id as other_tile_id,
             row_number() over(partition by a.tile_id order by b.min_x - a.min_x) as distance_rank
        from
            tile_data a
        inner join
            tile_data b
        on
            a.min_x < b.min_x
            and a.min_y = b.min_y
    ) ranked_tiles_right
    where
        distance_rank = 1
),
up_neighbor_tiles as
(
    select
        tile_id,
        other_tile_id as up_neighbor_tile_id
    from
    (
        select
            a.tile_id,
            b.tile_id as other_tile_id,
            row_number() over(partition by a.tile_id order by a.min_y - b.min_y) as distance_rank
        from
            tile_data a
        inner join
            tile_data b
        on
            a.min_y > b.min_y
            and a.min_x = b.min_x
    ) ranked_tiles_up
    where
        distance_rank = 1
)
select
    a.*,
    b.right_neighbor_tile_id,
    c.up_neighbor_tile_id
from
    tile_data a
left join
    right_neighbor_tiles b
on
    a.tile_id = b.tile_id
left join
    up_neighbor_tiles c
on
    a.tile_id = c.tile_id

结果:
tile_id  min_x  max_x  min_y  max_y  right_neighbor_tile_id   up_neighbor_tile_id
1        0      0.9    0      0.9    2
2        1      1.9    0      0.9    3
3        2      2.9    0      0.9
4        0      0.9    1      1.9    5                        1
5        1      1.9    1      1.9    6                        2
6        2      2.9    1      1.9                             3
7        0      0.9    2      2.9    8                        4
8        1      1.9    2      2.9    9                        5
9        2      2.9    2      2.9                             6

关于sql - SQL查询从具有二维数据的表中获取邻居,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4329775/

10-12 18:48