Sql 如何创建为每个用户查找最近存储的联接查询

Sql 如何创建为每个用户查找最近存储的联接查询,sql,ms-access,Sql,Ms Access,我有两张简单的桌子: User: id - int name - string lat - decimal long - decimal Store: id - int name - string lat - decimal long - decimal 我想有一个查询,可以得到最近商店的所有用户。我不关心地球的圆度,因为每个用户都会在附近有一家商店。这就是为什么我选择毕达哥拉斯来寻找最近的距离: SELECT User.*, Store.*, Sqr((User.

我有两张简单的桌子:

User:
id - int
name - string
lat - decimal
long - decimal

Store:
id - int
name - string
lat - decimal
long - decimal

我想有一个查询,可以得到最近商店的所有用户。我不关心地球的圆度,因为每个用户都会在附近有一家商店。这就是为什么我选择毕达哥拉斯来寻找最近的距离:

SELECT 
   User.*, 
   Store.*, 
   Sqr((User.Lat - Store.Lat)^2+(User.Long - Store.Long)^2) AS distance
FROM User, Store
不幸的是,这给了我笛卡尔积,所以我得到了所有用户与每个商店的距离。有没有办法只去最近的商店


谢谢

您可以按用户分组并计算最小值(距离),然后链接回第一个查询,以确定与用户的距离是哪个商店

这是您的查询,为了清晰起见,删除了一些字段(并使用了User.Id别名)

这将封装第一个查询,以计算每个用户到商店的最小距离

select userid, min(distance) from (
    SELECT 
        User.id as userid, 
        Sqr((User.Lat - Store.Lat)^2+(User.Long - Store.Long)^2) AS distance
    FROM User, Store
 ) as x 
group by userid
将其连接回原始查询以填充用户字段,并计算出与用户的(最小)距离是哪个存储


select z.*
from (
    select userid, min(distance) as distance from (
        SELECT 
            User.id as userid, 
            Sqr((User.Lat - Store.Lat)^2+(User.Long - Store.Long)^2) AS distance
        FROM User, Store
     ) as x 
group by userid
) as y inner join
(
    SELECT 
        User.Id as UserId, ... (populate the remaining user fields), 
        Store.*, 
        Sqr((User.Lat - Store.Lat)^2+(User.Long - Store.Long)^2) AS distance
    FROM User, Store
) as z
on y.userid = z.userid and y.distance = z.distance


您只需交叉连接表和WHERE子句,在该子句中,您可以选择与每个用户的最小距离的商店,如下所示:

select u.*, s.*
from user as u, store as s
where ((u.Lat - s.Lat)^2+(u.Long - s.Long)^2) = (
  select min((u.Lat - ss.Lat)^2+(u.Long - ss.Long)^2)
  from  store as ss
)

您不需要将
Sqr()
应用于计算。

因此,如果我理解正确,您有一个完整的用户列表,以及用户与笛卡尔空间中所有存储的相对距离?如果是这种情况,您可以始终使用
groupby
根据用户的
id
对条目进行分组,然后使用
orderby
按距离降序排序。然后,您可以查看这篇文章,了解如何通过获取每个
组的第一行,并根据您的需要对其进行调整,以根据当前查询返回您想要的结果。尝试使用Sqr等式仅获取一个结果,这正是我正在努力解决的部分。我正在使用Access,是否应该尝试顶部查询?听起来很有趣,明天将对此进行测试。谢谢
select u.*, s.*
from user as u, store as s
where ((u.Lat - s.Lat)^2+(u.Long - s.Long)^2) = (
  select min((u.Lat - ss.Lat)^2+(u.Long - ss.Long)^2)
  from  store as ss
)