当前位置:  开发笔记 > 编程语言 > 正文

在SQL或MySQL中不使用JOIN关键字的连接是否有问题?

如何解决《在SQL或MySQL中不使用JOIN关键字的连接是否有问题?》经验,为你挑选了4个好方法。

当我开始编写数据库查询时,我还不知道JOIN关键字,当然我只是扩展了我已经知道的并写了这样的查询:

SELECT a.someRow, b.someRow 
FROM tableA AS a, tableB AS b 
WHERE a.ID=b.ID AND b.ID= $someVar

现在我知道这和INNER JOIN一样,我在代码中找到所有这些查询,并问自己是否应该重写它们.他们有什么臭的或他们就好吗?


编辑:

我的回答摘要:此查询没有任何问题,但使用关键字最有可能使代码更易读/可维护.

我的结论是:我不会改变我的旧查询,但我将纠正我的写作风格,并在将来使用关键字.

谢谢你的回答!



1> Daniel Spiew..:

WHERE在某些常见情况下,仅使用过滤联接可能效率极低.例如:

SELECT * FROM people p, companies c 
    WHERE p.companyID = c.id AND p.firstName = 'Daniel'

大多数数据库将完全按字面意思执行此查询,首先获取和表的笛卡尔积,然后通过具有匹配和字段的那些进行过滤.虽然完全不受约束的产品不存在于存储器中的任何地方,但仅存在一段时间,但其计算确实需要一些时间.peoplecompaniescompanyIDid

更好的方法是将约束与JOIN相关的s 进行分组.这不仅在主观上更容易阅读,而且效率更高.正是如此:

SELECT * FROM people p JOIN companies c ON p.companyID = c.id
    WHERE p.firstName = 'Daniel'

它有点长,但数据库能够查看该ON子句并使用它来JOIN直接计算完全约束,而不是从所有内容开始然后限制.这样计算速度更快(特别是对于大型数据集和/或多表连接)并且需要更少的内存.

我改变了我看到的每个使用"逗号JOIN"语法的查询.在我看来,它存在的唯一目的是简洁.考虑到性能影响,我认为这不是一个令人信服的理由.


您能否提供使用旧连接语法执行笛卡尔积的数据库系统示例?旧语法很常见,我认为大多数DBMS优化器都知道不会这样做.
你说"大多数数据库"会生成"笛卡尔积".不是这样.许多关系数据库(DB2,Oracle,Sybase)早于SQL-92 JOIN语法.在此之前,所有连接谓词都在WHERE子句中.缺少连接谓词是导致笛卡尔积的原因.大多数数据库选择有效的访问路径,并且只选择"笛卡尔积"(如果该路径具有最低的计算成本)(或者如果它是唯一可用的访问路径,或者该语句是否被暗示).SQL-92 JOIN语法的一大优点是,语句中缺少连接谓词更为明显.
请您的DBMS向您解释这两个陈述.一个好的系统将使旧的SQL和SQL 1992连接语法执行等效的操作.

2> Forgotten Se..:

INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN用于连接的ANSI SQL/92语法越详细.对我来说,这种冗长使得连接对于开发者/ DBA更加清楚了解连接的意图.


它可以更容易地发现缺少的连接谓词.JOIN语法使错误的语句看起来错误.缺少连接谓词在旧式语法中更难以发现.

3> Meff..:

在SQL Server中总是有要检查的查询计划,文本输出可以按如下方式进行:

SET SHOWPLAN_ALL ON
GO

DECLARE @TABLE_A TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_A
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

DECLARE @TABLE_B TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_B
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A, @TABLE_B AS B
WHERE
    A.ID = B.ID

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A
    INNER JOIN @TABLE_B AS B ON A.ID = B.ID

现在我将省略表变量创建的计划,但两个查询的计划是相同的:

 SELECT A.Data, B.Data  FROM   @TABLE_A AS A, @TABLE_B AS B  WHERE   A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)
 SELECT A.Data, B.Data  FROM   @TABLE_A AS A   INNER JOIN @TABLE_B AS B ON A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)

所以,简短的回答 - 不需要重写,除非你每次维护它们都花了很长时间试图阅读它们?



4> Powerlord..:

它更像是一种语法选择.我更喜欢将连接条件与我的连接分组,因此我使用INNER JOIN语法

SELECT a.someRow, b.someRow
FROM tableA AS a
INNER JOIN tableB AS b
  ON a.ID = b.ID
WHERE b.ID = ?

(?作为占位符)

推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有