Postgresql获得特定半径的用户

时间:2017-07-19 11:09:20

标签: postgresql postgis

我试图让所有提出请求的用户获得半径范围内的用户。我创建了一个gps(几何类型)来存储纬度和经度。

我已使用此代码:

SELECT * From UserAddresses 
WHERE ST_DWithin(
   (Select gps 
    from useraddresses 
    where ID=(Select UserAddressID 
              FROM Users WHERE ID=1)), 
   (Select gps 
    from useraddresses 
    WHERE ID IN (SELECT UserAddressID 
                 FROM Users 
                 WHERE ID!=1)), 
    1609*(Select DiscoveryDistance 
          From Users 
          WHERE ID=1),true)

但它会返回此错误:

  

错误:用作表达式

的子查询返回多行

我知道此错误来自SELECT UserAddressID FROM Users WHERE ID!=1部分,但我无法解决。

我想要做的就是将GPS ID=1与所有用户进行比较,如果他们在半径范围内获取他们的数据。

任何人都可以帮我解释语法吗?

2 个答案:

答案 0 :(得分:0)

您可以将条件移到子查询之外。 ST_DWithin一次处理1行(对于每个几何)​​,因此如果使用子查询,它也必须只返回一行,并且您可能有多行ID!=1

SELECT targetAdr.* 
From UserAddresses srcAdr,
     UserAddresses targetAdr
WHERE srcAdr.ID=(Select UserAddressID 
                 FROM Users 
                 WHERE ID=1)
AND targetAdr.ID IN (SELECT UserAddressID 
                     FROM Users 
                     WHERE ID!=1)
AND ST_DWithin(srcAdr.gps, 
               targetAdr.gps, 
               1609*srcAdr.DiscoveryDistance,
               true);

请注意,根据您分配addressID的方式,简单地执行AND targetAdr.ID != srcAdr.ID而不是可能很大的IN子句可能会更有效。

答案 1 :(得分:0)

我假设您将“gps”列作为具有指标SRID的几何类型,或者如果您使用4326,则表示您具有地理位置类型

SELECT *
  FROM UserAddresses ua1
 WHERE EXISTS (SELECT FROM users u1, UserAddresses ua2, users u2 
                WHERE u2.id=1 
                  AND u1.id<>u2.id
                  AND u1.useraddressid=ua1.id
                  AND u2.useraddressid=ua2.id 
                  AND st_DWithin(ua2.gps, ua1.gps, u2.DiscoveryDistance*1609))

请记住使用GiST索引索引gps列。