SQL - 依赖于 2 个表的查询?
Posted
技术标签:
【中文标题】SQL - 依赖于 2 个表的查询?【英文标题】:SQL - query that dependent on 2 tables? 【发布时间】:2013-12-11 21:07:50 【问题描述】:我有一个包含 2 个表的数据库:
-
企业。
优惠券
Businesses
中的每一行都有以下字段:
id
, details
, image
, name
, location_x
, location_y
,
其中location_x
和location_y
是谷歌地图的latitue
和longitue
坐标。
在Coupons
表中,每一行都有以下字段:
id
, business_id
, image
, details
, goneDate
, goneHour
。
id
是优惠券id
,
而business_id
是这张优惠券所属的business
的id
。
我的问题:
通过查询Coupons
,如何从给定坐标中获取其所有者业务位置半径小于10km
的所有优惠券?
或者换句话说,就是这样的人:
如何获取每个优惠券商家id,然后到商家表中,查看商家id位置的半径是否小于给定位置10公里?
我认为它与inner join
有关,不确定。
我正在使用 Java 的 hibernate 框架工作。
请帮助我,在此先感谢!
【问题讨论】:
只要知道根据地图坐标计算距离的公式,剩下的就是小菜一碟了INNER JOIN
。
您使用的是什么数据库引擎?例如,SQL Server 支持内置空间坐标。
@PM77-1 如何使用INNER JOIN
?
Sql 服务器?没有 francis OP 表示他正在使用 nhibernate,他需要链接或 hql。顺便说一句,在 where 子句中放置 WHERE (X 在坐标 - 10km 和坐标 + 10km 之间) AND(samething to Y)
在这种情况下,这可能会有所帮助:dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html
【参考方案1】:
这可以通过数学来完成!
首先我们知道给定一个Point P(x, y)
,P
位于Circle
内,Center C(a,b)
和Radius r
如果它满足方程(x-a)^2 + (y - b)^2 <= r^2
。
因此,在您的情况下,中心将是提供的初始坐标。
为了获取位于给定半径内的企业的所有优惠券,这个查询应该可以解决问题。
SELECT
bus.id, coup.id
FROM
Businesses AS bus INNER JOIN
Coupons AS coup
WHERE
bus.id = coup.business_id AND
(acos(sin(radians(business.location_y)) * sin(radians(a)) + cos(radians(business.location_y)) * cos(radians(a)) * cos(radians(business.location_x) - radians(b)) * 6371) <= 10;
在上述查询a is input_y
和b is input_x
和r is the radius = 10
。查询假设地球半径为 6371 KM。
已编辑:在与@acfrancis 讨论后,我使用更适合计算球体上点之间距离的方程重写了查询。这应该适用于您的用例(即使地球不是完美的球体)。使用的所有函数都是 postgres 特定的。详情可以看这里http://en.wikipedia.org/wiki/Great-circle_distance。
【讨论】:
不要将纬度/经度与笛卡尔平面上的 X/Y 坐标混淆。例如,同一纬度且相隔 1 度经度的两点之间的距离取决于纬度。靠近两极,距离很小,但在赤道上,距离很大。正确的计算并非易事。这就是为什么我建议尽可能使用内置功能。 是的,你是绝对正确的。但是在用例中,在 10 公里距离处描述的 OP 使用这个方程的误差范围可以忽略不计。如果用例需要高精度,那么提出查询将有点困难:) 这不是精度问题。您的公式返回应用于这两组点的相同距离,以(纬度,经度)度为单位:[(0, 0); (0, 0.1)] 和 [(180, 0); (180, 0.1)]。第一组在赤道上,实际距离约11km。第二秒在北极,距离为零。 首先没有纬度180度这样的东西。有效范围是 -90 到 +90。其次,即使您的意思是 (long, lat)=(180,0),那仍然不是北极。北极是 (90,0)。无论如何,这种解决方案显然并不完美,但如果不采取极端情况,它就可以完成这项工作。 至于其余部分,location_x、location_y、a 和 b(最有可能)是十进制度。将它们(where 子句表达式的左侧)与 km(右侧)进行比较是没有意义的。【参考方案2】:我认为这不能仅在 SQL 中完成,因为您需要进行一些计算来确定企业与给定位置之间的距离。
可以查询商家,计算所有距离,扔掉超过 10 公里的距离,然后查询优惠券。
SELECT * FROM coupons WHERE business_id IN array of your <10km business ids
如果您只是想获得与企业内部加入匹配的优惠券的结果,那么您会工作
SELECT * FROM coupons INNER JOIN businesses ON coupons.business_id = businesses.id
【讨论】:
【参考方案3】:您必须使用公式计算距离。您的问题在这里有答案:Finding a geography point within a range of another - SQL Server
【讨论】:
以上是关于SQL - 依赖于 2 个表的查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 3 个表在 SQL 查询中获得完整结果,其中 1 个表保持 2 个表的关系?
跨 2 个表的 Mysql SQL 查询 - 不知道如何正确执行