【问题标题】:Adding A JOIN To A MySQL Query Is Throwing Strange Error向 MySQL 查询添加 JOIN 会引发奇怪的错误
【发布时间】:2014-07-16 21:36:10
【问题描述】:

我正在创建一个 MySQL 程序。这些表格及其数据由 MAXMIND 的位置 IP 服务提供,可以在here 找到。 PROCEDURE 不是由我创建的,但它完全可以满足我的需要,除非我试图向查询中添加一个 JOIN。我正在尝试获取“目的地”的 id 并查询照片表以获取照片。

表格

|   locations    ||     photos     |
|________________||________________|
 |              |  |              | 
 |      id      |  |     id       |  
 |   latitude   |  |    lid       |
 |   longitude  |  |    pid       |

守则:

CREATE PROCEDURE `GEODIST`( IN userid int, IN dist int, IN olat float, IN olon float ) DETERMINISTIC READS SQL DATA

BEGIN
DECLARE mylon DOUBLE;
DECLARE mylat DOUBLE;
DECLARE lon1 FLOAT;
DECLARE lon2 FLOAT;
DECLARE lat1 FLOAT;
DECLARE lat2 FLOAT;

SET mylon = olon;
SET mylat = olat;
SET lon1 = mylon - dist / abs( cos( radians( mylat ) ) * 69 );
SET lon2 = mylon + dist / abs( cos( radians( mylat ) ) * 69 );
SET lat1 = mylat - ( dist / 69 );
SET lat2 = mylat + ( dist / 69 );

SELECT destination.id, destination.latitude, destination.longitude, photos.lid,
photos.pid, 3956 * 2 * ASIN(SQRT( POWER(SIN((origin.latitude -destination.latitude) * pi()/180 / 2), 2) +COS(origin.latitude * pi()/180) * COS(destination.latitude * pi()/180) *POWER(SIN((origin.longitude -destination.longitude) * pi()/180 / 2), 2) )) AS distance 
FROM locations destination, locations origin JOIN photos ON photos.lid = destination.id WHERE origin.id = userid
AND destination.longitude BETWEEN lon1 AND lon2 AND destination.latitude BETWEEN lat1 and lat2 
HAVING distance < dist ORDER BY distance LIMIT 50;
END

问题是,当我调用 PROCEDURE 时,我收到以下错误:

 #1054 - Unknown column 'destination.id' in 'on clause'

如果查询中没有 JOIN 子句,一切正常。查询正常工作,所以我知道它与 JOIN 有关,但我不知道发生了什么。非常感谢任何帮助。

【问题讨论】:

  • 重做我的评论 - 位置目的地和位置来源之间的关系是什么?交叉加入?
  • @Twelfth 这是一个故意的 CROSS JOIN(交叉自连接),因此您可以获得起点和终点的所有组合以获取所有位置之间的距离......然后过滤掉想要的那些组合。
  • @VMai 这就是我所怀疑的......正在确认,因为他在那里混合了连接语法。嘿,你通过不确认而只是回答来击败我的答案:)
  • 要么放弃连接运算符的老式逗号语法并使用 JOIN 关键字,或者 - 将连接谓词移动到 WHERE 子句。不要混合使用老式逗号语法和 JOIN .. ON 语法。

标签: php mysql performance stored-procedures join


【解决方案1】:

您不应该将逗号运算符和显式连接混为一谈:

...
FROM locations destination, locations origin JOIN photos ON photos.lid = destination.id
...

您应该改用 CROSS JOIN:

FROM locations destination CROSS JOIN locations origin JOIN photos ON photos.lid = destination.id

手册章节JOIN Syntax对此进行了解释:

INNER JOIN 和 ,(逗号)在没有 一个连接条件:两者都产生一个笛卡尔积 指定的表(即第一个表中的每一行都是 连接到第二个表中的每一行)。

但是,逗号运算符的优先级低于 INNER JOIN、CROSS JOIN、LEFT JOIN 等等。如果您将逗号连接与 当存在连接条件时,其他连接类型的错误 可能会出现“on 子句”中的表单未知列“col_name”。

【讨论】:

  • 谢谢,感谢您的帮助。我希望获取所有目的地,然后获取与这些目的地相关联的所有照片,也许我在这里做错了,但这次查询实际上运行了,这是向前迈出的一大步,但它只为我提供了有照片的目的地,它没有为我提供照片表中没有任何列表的任何目的地。非常感谢您的帮助。
  • 它提供相同的结果并复制与照片一样多的次数:例如,如果 location1 有 5 张照片,则结果中有 5 个 location1,但如果 location2 没有照片,那么 location2 根本不在结果列表中。
  • @mcbeav 要获取没有照片的位置,请使用左连接。要为每个位置仅获取一行而不是每张照片一行,您可以添加 GROUP BY destination.id 子句并在您的照片列上使用聚合函数 GROUP_CONCAT。顺便说一句,性能会更差。也许您应该在一个新问题中对此进行探索。请提供样本数据和期望的结果。
  • 这很有趣。谢谢你的信息,我很感激。我会看看我能用这个做什么。谢谢!
【解决方案2】:

这是您的from 子句:

FROM locations destination,
     locations origin JOIN
     photos
     ON photos.lid = destination.id
WHERE origin.id = userid AND
      destination.longitude BETWEEN lon1 AND lon2 AND
      destination.latitude BETWEEN lat1 and lat2 

您正在混合隐式和显式连接。这是一个坏主意,现在您至少知道一个原因。你会得到奇怪的错误。一个简单的规则:永远不要在from 子句中使用逗号。

您可以通过将, 替换为cross join 来解决此问题:

FROM locations destination CROSS JOIN
     locations origin JOIN
     photos
     ON photos.lid = destination.id
WHERE origin.id = userid AND
      destination.longitude BETWEEN lon1 AND lon2 AND
      destination.latitude BETWEEN lat1 and lat2 

CROSS JOIN 与逗号几乎完全相同。除了,from 子句的其余部分已知第一个表中的列。但是,您应该真正修复joins。这是一个猜测:

FROM photos JOIN
     locations destination
     ON photos.lid = destination.id JOIN
     locations origin
     ON origin.id = userid
WHERE destination.longitude BETWEEN lon1 AND lon2 AND
      destination.latitude BETWEEN lat1 and lat2 

【讨论】:

  • 这是很好的信息。我要试一试,我对 MySQL 不太熟悉,还在学习中。这对我来说都是新的。谢谢你的帮助。我要试试这个并报告。谢谢!
  • 谢谢,感谢您的帮助。我希望获取所有目的地,然后获取与这些目的地相关联的所有照片,也许我在这里做错了,但这次查询实际上运行了,这是向前迈出的一大步,但它只为我提供了有照片的目的地,它没有为我提供照片表中没有任何列表的任何目的地。非常感谢您的帮助。
  • 我尝试完全按照第一段代码中的建议使用交叉连接。
  • 我刚刚尝试将代码更改为您提供的代码的底部部分,看来我得到了相同的结果。它提供相同的结果并复制与照片一样多的次数:例如,如果 location1 有 5 张照片,则结果中有 5 个 location1,但如果 location2 没有照片,则 location2 不在结果列表中完全没有。
  • @mcbeav 。 . .您原始查询中的逻辑根本不正确。但是,您的问题是关于语法问题,而不是逻辑问题。我建议你再问一个问题,包括样本数据和期望的结果。
猜你喜欢
  • 2020-12-02
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 2014-08-15
  • 2013-02-28
  • 2022-06-13
  • 2011-09-04
  • 1970-01-01
相关资源
最近更新 更多