2个sql查询有啥区别?

Posted

技术标签:

【中文标题】2个sql查询有啥区别?【英文标题】:What is difference between 2 sql queries?2个sql查询有什么区别? 【发布时间】:2016-11-21 15:51:24 【问题描述】:

我有 2 个 sql 查询,其中一个可以工作,但另一个出错。以下查询效果很好

select /*ordered*/ coupon_address.coupon,merchant_address.id  
from merchant_address, 
     coupon_address, 
     customers c  
WHERE merchant_address.id = coupon_address.merchant_address 
  and c.CUSTOMER_ID = 'temp1' 
  AND sdo_within_distance(c.cust_geo_location,merchant_address.store_geo_location,'distance = 1 unit=MILE') = 'TRUE';

但以下查询不起作用并给出错误

select /*ordered*/ coupon_address.coupon,merchant_address.id  
from  coupon_address, 
      customers c 
  JOIN merchant_address ON merchant_address.id=coupon_address.merchant_address
 WHERE c.CUSTOMER_ID = 'temp1' 
   AND sdo_within_distance (c.cust_geo_location,merchant_address.store_geo_location, 'distance = 1 unit=MILE') = 'TRUE';

错误是

第 1 行出现错误:ORA-00904:“COUPON_ADDRESS”。“MERCHANT_ADDRESS”:标识符无效

【问题讨论】:

您将旧的、古老的、过时的和脆弱的隐式连接与显式的JOIN 运算符混合在一起。不要那样做。 如果你使用ANSI语法,你必须对所有的表都使用它;同样,如果您决定使用旧的 Oracle 连接语法(强烈建议不要这样做),请对所有表执行此操作 @a_horse_with_no_name 将过时的连接与 JOIN 混合是什么意思? 包含表定义 【参考方案1】:

永远不要将显式和隐式连接语法混合在一起!它们总是会导致混乱和错误:

select /*ordered*/ coupon_address.coupon,merchant_address.id
FROM coupon_address
JOIN merchant_address
  ON merchant_address.id=coupon_address.merchant_address
JOIN customers c ON c.CUSTOMER_ID = 'temp1'
WHERE  sdo_within_distance (c.cust_geo_location,
                            merchant_address.store_geo_location, 
                           'distance = 1 unit=MILE') = 'TRUE';

它不起作用的原因是解析器评估查询的顺序。可能未知列的表尚未评估。

【讨论】:

我敢打赌这并不能解决实际问题,而是应该作为评论。已经发表的评论。 这确实有效,但我不确定我写的加入语句有什么问题。 问题在于优化器评估查询的顺序。可能未知列的表尚未评估。 @raju @alfabravo 关于什么? :) 这是因为在您的原始查询中,您尝试使用 ANSI 语法将客户表内部连接到商家地址表,但连接条件是针对不同的表。如果你有from customers, coupon_address inner join merchant_address on merchant_address.id = coupon_address.merchant_address,它可能会起作用,尽管我不推荐它。在整个查询过程中坚持使用一种连接语法,您不会感到困惑。【参考方案2】:

JOIN 的优先级高于 FROM 子句中的 ,ONJOIN 的一部分,因此它只能看到开始加入的内容,包括早期的加入。

所以:

select /*ordered*/ coupon_address.coupon,merchant_address.id  
from  coupon_address, 
      customers c 
  JOIN merchant_address
    ON merchant_address.id=coupon_address.merchant_address

本质上是:

select /*ordered*/ coupon_address.coupon,merchant_address.id  
from  coupon_address, 
      (customers c 
  JOIN merchant_address
    ON merchant_address.id=coupon_address.merchant_address)

coupon_address 尚未在范围内。

正如其他人所说,最好坚持一种连接方式,SQL-92 join 关键字或from 子句中的早期逗号和where 子句中的连接条件。我更喜欢明确的join 语法。

【讨论】:

错了! 最好坚持使用一种类型的join。最好使用正确、明确的JOIN 语法。【参考方案3】:

Sagi 的回答是正确的。您的版本不起作用的原因是因为 FROM 子句中逗号周围的范围规则。哦,我有没有提到:从不FROM 子句中使用逗号。 总是使用明确的JOIN 语法。

您的 FROM 子句被评估为:

from coupon_address, 
     (customers c JOIN
      merchant_address
      ON merchant_address.id = coupon_address.merchant_address
     )

我认为这很清楚你为什么会收到错误。

【讨论】:

以上是关于2个sql查询有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

在Oracle数据库条件查询语句中使用'%%','_%%'这两个有啥区别

SQL Server 中这两个循环删除查询有啥区别

SQL数据库中查询语句Order By和Group By有啥区别

数据库的SQL语句中,嵌套查询和连接查询有啥区别,说的详细的

下面有两个sql查询有啥区别

sql语句中嵌套时候用in 和=有啥区别