Mysql JOIN多个具有纬度和经度的表

时间:2014-10-25 00:15:21

标签: mysql

我正在尝试显示与用户数据相关的广告 这里的数据是纬度和经度。

ADS表:广告,包含广告名称,广告文字,经度和纬度

包含用户数据的表格:
TABLE1:用户ID + 纬度和经度
TABLE2:用户ID + 纬度和经度
TABLE3:用户ID + 纬度和经度
TABLE4:用户ID + 经度和纬度

目的是在广告的纬度和经度与10个范围内的4个表格中一个或多个行的纬度和经度相匹配时显示广告,并限制为3个结果

将一个广告与10公里范围内的一张广告相关联时,它会正常工作,但不会有更多的广告素材   - 我对OUTER JOINS -

感到不舒服

我的查询看起来像这样,我很确定我错了......

SELECT ADS.name, ADS.text, 
( 6371 * acos( cos( radians(TABLE1.latitude) ) 
 * cos( radians( ADS.latitude ) ) 
 * cos( radians( ADS.longitude ) 
 - radians(TABLE1.longitude) ) 
 + sin( radians(TABLE1.latitude) ) 
 * sin( radians( ADS.latitude ) ) ) ) 
 AS check1, 

 ( 6371 * acos( cos( radians(TABLE2.latitude) ) 
 * cos( radians( ADS.latitude ) ) 
 * cos( radians( ADS.longitude ) 
 - radians(TABLE2.longitude) ) 
 + sin( radians(TABLE2.latitude) ) 
 * sin( radians( ADS.latitude ) ) ) ) 
 AS check2, 

 ( 6371 * acos( cos( radians(TABLE3.latitude) ) 
 * cos( radians( ADS.latitude ) ) 
 * cos( radians( ADS.longitude ) 
 - radians(TABLE3.longitude) ) 
 + sin( radians(TABLE3.latitude) ) 
 * sin( radians( ADS.latitude ) ) ) ) 
 AS check3, 

 ( 6371 * acos( cos( radians(TABLE4.latitude) ) 
 * cos( radians( ADS.latitude ) ) 
 * cos( radians( ADS.longitude ) 
 - radians(TABLE4.longitude) ) 
 + sin( radians(TABLE4.latitude) ) 
 * sin( radians( ADS.latitude ) ) ) ) 
 AS check4 

FROM ADS 
RIGHT OUTER JOIN TABLE1 
ON TABLE1.user = ? 
RIGHT OUTER JOIN TABLE2 
ON TABLE2.user = ? 
RIGHT OUTER JOIN TABLE3 
ON TABLE3.user = ? 
RIGHT OUTER JOIN TABLE4 
ON TABLE4.user = ? 
HAVING check1 < 10 OR check2 < 10 OR check3 < 10 OR check4 < 10 
LIMIT 0,3 

2 个答案:

答案 0 :(得分:2)

如果user(或任何TABLEn)中的TABLE1不唯一,则可能会从ADS返回同一行的多个副本。

使用查询的方式,如果在TABLE4中找不到指定的用户,则查询将不返回任何行。我怀疑你的意思是LEFT JOINADS作为驾驶表,但这只是猜测。我们不知道这些表包含什么,为什么有四个表等等。)

如果您使用RIGHT JOIN的原因,以及带有一个表的查询是否适合您...

如果指定用户的TABLE1,TABLE2,TABLE3,TABLE4中的每一行都有少量行...

您可以将这些表的查询结果连接到单个派生表中,然后连接到派生表。举个例子:

 SELECT ADS.name, ADS.text, 
 ( 6371 * acos( cos( radians(t.latitude) ) 
 * cos( radians( ADS.latitude ) ) 
 * cos( radians( ADS.longitude ) 
 - radians(t.longitude) ) 
 + sin( radians(t.latitude) ) 
 * sin( radians( ADS.latitude ) ) ) 
 )  AS check1
   FROM ADS
  RIGHT
   JOIN ( SELECT TABLE1.latitude, TABLE1.longitude
            FROM TABLE1 WHERE TABLE1.user = ?
           UNION ALL
          SELECT TABLE2.latitude, TABLE2.longitude
            FROM TABLE2 WHERE TABLE2.user = ?
           UNION ALL
          SELECT TABLE3.latitude, TABLE3.longitude
            FROM TABLE3 WHERE TABLE3.user = ?
           UNION ALL
          SELECT TABLE4.latitude, TABLE4.longitude
            FROM TABLE4 WHERE TABLE4.user = ?
        ) t
 HAVING check1 < 10
  LIMIT 3 

答案 1 :(得分:0)

这最终是我所需要的:

$reponse = $bdd->prepare('
SELECT * FROM
(
SELECT ADS.id AS id, ADS.name, ADS.text, 
( 6371 * acos( cos( radians(t.latitude) ) 
 * cos( radians(ADS.latitude ) ) 
 * cos( radians( ADS.longitude ) 
 - radians(t.longitude) ) 
 + sin( radians(t.latitude) ) 
 * sin( radians( ADS.latitude ) ) ) ) 
 AS distance 
 FROM ADS 
RIGHT  
   JOIN ( SELECT TABLE1.latitude, TABLE1.longitude
            FROM TABLE1 WHERE TABLE1.user = :user 
           UNION ALL 
          SELECT TABLE2.latitude, TABLE2.longitude
            FROM TABLE2 WHERE TABLE2.user = :user 
           UNION ALL 
          SELECT TABLE3.latitude, TABLE3.longitude 
            FROM TABLE3 WHERE TABLE3.user = :user 
           UNION ALL 
          SELECT TABLE4.latitude, TABLE4.longitude 
            FROM TABLE4 WHERE TABLE4.user = :user 
        ) t 
        ON 1 
 HAVING distance < 10
) req GROUP BY id LIMIT 0,3
');   
$reponse->execute(array('user' => $_SESSION['id']));