【问题标题】:In SQL server what is the difference between using = and join?在 SQL Server 中,使用 = 和 join 有什么区别?
【发布时间】:2016-08-23 23:45:02
【问题描述】:

我们一直在数据库系统课程中学习 SQL Server 编程。教授走得特别快,而且对提问不是很开放。我确实问过他这个问题,但他只是建议我查看他给出的代码(实际上并没有回答问题)。

在进行查询时,使用术语 JOIN 和使用“=”运算符有什么区别?例如,我有以下查询:

SELECT VENDOR_NAME, ITEM_NAME, QTY
FROM   VENDOR, VENDOR_ORDER, INVENTORY
WHERE  VENDOR.VENDOR_ID = VENDOR_ORDER.VENDOR_ID
 AND  VENDOR_ORDER.INV_ID = INVENTORY.INV_ID
ORDER  BY VENDOR_NAME

教授在课堂上使用了以下代码:

SELECT DISTINCT CUS_CODE, CUS_LNAME, CUS_FNAME 
FROM CUSTOMER   JOIN INVOICE USING (CUS_CODE)
        JOIN LINE USING (INV_NUMBER) 
        JOIN PRODUCT USING (P_CODE)
WHERE P_DESCRIPT = 'Claw hammer';

在我看来,使用连接执行的功能与我的“=”相同?我是正确的还是有我不知道的差异?

编辑: 尝试根据我在 Google 上找到的内容使用 Inner Join。我最终得到了以下结果。

SELECT VENDOR_NAME, ITEM_NAME, QTY
FROM   VENDOR, VENDOR_ORDER, INVENTORY
        INNER JOIN VENDOR_ORDER USING (VENDOR_ID)
        INNER JOIN INVENTORY USING (INV_ID)
ORDER  BY VENDOR_NAME

现在我收到错误消息““VENDOR_ID”不是可识别的表提示选项。如果它打算作为表值函数或 CHANGETABLE 函数的参数,请确保您的数据库兼容模式设置为 90 . " 我用的是2014,所以我的兼容级别是120。

【问题讨论】:

  • 您使用的是旧的旧连接语法。像教授一样使用显式连接语法
  • 该语法在 SQL Server 类中?
  • 所以他们在做同样的事情,但是 JOIN 是首选?此外,它会使大型查询运行得稍微快一些吗?
  • 据我所知,USING 在 SQL Server 中不起作用。您应该使用带有 ON 子句的显式 JOIN 语法。

标签: sql-server join equals-operator


【解决方案1】:

别担心,这是您的教授的问题,而不是您的问题。确保您在课程结束时提供适当的反馈;)

坚持住。

所以这里有一些信息:

所以第一个问题是:你的教授不应该教你USING,因为它的实现有限(它肯定不会在 SQL Server 中工作),恕我直言,这是一个坏主意,因为你应该明确列出连接列。

这里有一些可以在 SQL Server 中运行的查询 - 让我们一点一点地构建它们。我需要做一些假设

首先将供应商加入供应商订单:

SELECT VENDOR.VENDOR_NAME, VENDOR_ORDER.QTY
FROM   VENDOR
INNER JOIN 
VENDOR_ORDER
ON VENDOR.VENDOR_ID = VENDOR_ORDER.VENDOR_ORDER

通过使用内连接,我们匹配VENDOR_ID上的这两个表

如果您在VENDOR_ORDER 中有 7 条记录且 VENDOR_ID = 7,并且在表 VENDOR 中有一条记录,那么结果将是.... 7 条记录,VENDOR 表中的数据重复 7 条次。

现在,加入库存

SELECT VENDOR.VENDOR_NAME, INVENTORY.ITEM_NAME, VENDOR_ORDER.QTY
FROM   VENDOR
INNER JOIN 
VENDOR_ORDER
ON VENDOR.VENDOR_ID = VENDOR_ORDER.VENDOR_ORDER
INNER JOIN
INVENTORY ON INVENTORY.INV_ID = VENDOR_ORDER.INV_ID
ORDER  BY VENDOR.VENDOR_NAME

这种“INNER JOIN”语法是现代版本(通常称为 SQL-92)。在 FROM 子句之后有一个逗号分隔的列表是“老派”

这两种方法的工作方式相同,但如果您开始使用外连接,旧式方法会导致歧义。所以要养成用新方法做这件事的习惯。

最后,您可以使用“别名”来整理内容。这意味着您给每个表一个较短的名称,然后使用它。我还添加了发票编号,以便您了解发生了什么:

SELECT V.VENDOR_NAME, I.ITEM_NAME, ORD.INV_ID, ORD.QTY
FROM   VENDOR As V
INNER JOIN 
VENDOR_ORDER As ORD
ON V.VENDOR_ID = ORD.VENDOR_ORDER
INNER JOIN
INVENTORY As I ON I.INV_ID = ORD.INV_ID
ORDER  BY V.VENDOR_NAME

【讨论】:

  • 谢谢,这也有帮助。我经常感到不知所措,因为速度如此之快而无法得到足够的答案来回答我的问题。至少我的 Google-fu 正在锻炼!
  • 使用别名时,是否必须逐个声明?我看到你在哪里有“VENDOR as V”,但其他地方没有。 SQL 只是“知道”吗?
  • 嗯,有VENDOR_ORDER as ORDINVENTORY As I 所以这两个表也有别名
  • (回答 Inessaria 的问题,而不是批评 Nick 的回答,这很有帮助)。除非您在多个表中具有相同名称的列,否则您不必使用别名;例如,如果您的 vendor 表中只有 vendor_ID,SQL 将知道您在没有别名的情况下的意思。您还可以在指定列时使用整个表名,尽管大多数人会分配较短的别名。 IMO 最好使用别名,即使您不必这样做,以使您的代码更清晰。
  • 我现在确实看到了别名分配,但它们出现在使用别名的开头行之后。在 Java 中,我习惯于按顺序排列,因此在分配别名之前使用别名会出错。这在 SQL 中有什么不同吗?它是否会在执行前检查整个表达式,从而查看别名分配而不返回错误?
【解决方案2】:

您正在做的事情(在您的第一个示例中)与您的教授正在做的事情之间的区别在于,您正在创建这些表中行的所有可能组合,然后将结果缩小到与你希望他们的方式。他首先创建了一组与您希望它们匹配的行。

如果您的桌子是:

Table1
ID1
1   
2    
3    

Table2
ID2
1    
2    
3    

您的查询基本上以交叉连接开始:

Select * from Table1, Table2

ID1  ID2
1    1
2    1
3    1
1    2
2    2
3    2
1    3
2    3
3    3

然后通过应用 where ID1 = ID2 缩小结果集

ID1  ID2
1    1
2    2
3    3

正如人们在 cmets 中提到的那样,这在更复杂的示例中效率低且难以阅读。

您的教授正在构建将两个表关联到联接本身的标准,因此他实际上跳过了第一步。在我们的示例表中,这将是 Select * from Table1 join Table2 on ID1 = ID2

SQL 中有多种类型的联接,根据您希望如何处理其中一个表中存在值但在另一表中不匹配的情况而有所不同。参见http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins的传统维恩图解释:

【讨论】:

  • 这是一个可爱的答案,并且很好地向我解释了它。那么使用下面的代码而不是 m original 会是正确的吗? SELECT VENDOR_NAME, ITEM_NAME, QTY FROM VENDOR INNER JOIN VENDOR_ORDER ON VENDOR.VENDOR_ID = VENDOR_ORDER.VENDOR_ID INNER JOIN INVENTORY ON VENDOR_ORDER.INV_ID=INVENTORY.INV_ID
  • 我不同意。在功能和性能方面没有区别。不要宣传这个神话。如果您查看两种语法之间的查询计划,它们的作用完全相同。您还发布了我最不喜欢的连接解释图表,它没有解释一对多连接中发生的关键概念之一......您得到很多记录,而不是一条!
  • @Inessaria - 是的,看起来不错(前提是您只打算在所有三个表中返回具有值的行)。
  • @Nick.McDermaid,我并没有说存在性能差异 - 我只是想一步一步地解释逻辑在做什么。很抱歉你不喜欢维恩图;请随时发布您自己的答案,解释您认为合适的不同类型的连接。
  • “这是低效的”..也许你指的是低效地编写代码。同样,如果您查看查询计划,您将看不到交叉连接,但我想您是在概念上解释它,在这种情况下,我认为您已经做得很好了 :)
猜你喜欢
  • 2014-02-07
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 2010-09-07
相关资源
最近更新 更多