【问题标题】:Mysql JOIN multiple tables with latitude and longitudeMysql JOIN 多张经纬度表
【发布时间】:2014-12-20 21:18:50
【问题描述】:

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

ADS 表格:要显示的广告,包含广告名称、广告文字、纬度和经度

有用户数据的表:
TABLE1: 用户id + 经纬度,
TABLE2: 用户id + 经纬度 >,
TABLE3: 用户id + 经纬度,
TABLE4: 用户id + 经纬度

目的是展示广告,当广告的经纬度与10km范围内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 

【问题讨论】:

    标签: mysql


    【解决方案1】:

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

    按照目前的查询方式,如果在 TABLE4 中找不到指定的用户,则查询不会返回任何行。我怀疑你的意思是LEFT JOIN,以ADS 作为驱动表,但这只是一个猜测。我们不知道那些表包含什么,为什么有四个,等等)

    如果您使用 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 
    

    【讨论】:

    • 确实我需要使用 LEFT JOIN。 RIGHT JOIN 正在处理一张桌子,因为第二张桌子上有结果,但不一定是这样。我正在尝试您的查询
    • 好像有错误; PhpmyAdmin 中的 SQL 查询说 错误接近 HAVING check1
    • @gr3g:我看到我在内联视图查询中犯了一个错误,第四个 SELECT 应该引用 TABLE4 而不是 TABLE2。 (我发布的查询保证会导致错误。您可以只运行内联视图查询来查看错误。)否则,我的示例查询与您发布的查询相同,除了将对 TABLE1 的引用替换为内联视图。我将别名t 分配给内联视图,因此我更改了check1 表达式中引用的限定符(将TABLE1. 替换为t.
    • 还有一个ON 也不见了
    • @gr3g: 或者,您可以删除 RIGHT 关键字,因为 HAVING 子句中的谓词将消除任何不匹配的行。添加关键字CROSS 不会更改查询,但作为没有 JOIN 谓词的文档,来自 ADS 的每一行都将连接到来自 t 的每一行。 (正如我在回答中指出的那样,尚不清楚您为什么使用 RIGHT JOIN ...我将您的查询保持原样(没有 ON 子句...我所做的唯一更改是替换使用内联视图引用 TABLE1
    【解决方案2】:

    这就是我最终需要的:

    $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'])); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-10
      • 2013-12-29
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 2019-04-21
      • 1970-01-01
      • 2012-02-15
      相关资源
      最近更新 更多