当我开始编写数据库查询时,我还不知道JOIN关键字,当然我只是扩展了我已经知道的并写了这样的查询:
SELECT a.someRow, b.someRow FROM tableA AS a, tableB AS b WHERE a.ID=b.ID AND b.ID= $someVar
现在我知道这和INNER JOIN一样,我在代码中找到所有这些查询,并问自己是否应该重写它们.他们有什么臭的或他们就好吗?
编辑:
我的回答摘要:此查询没有任何问题,但使用关键字最有可能使代码更易读/可维护.
我的结论是:我不会改变我的旧查询,但我将纠正我的写作风格,并在将来使用关键字.
谢谢你的回答!
WHERE
在某些常见情况下,仅使用过滤联接可能效率极低.例如:
SELECT * FROM people p, companies c WHERE p.companyID = c.id AND p.firstName = 'Daniel'
大多数数据库将完全按字面意思执行此查询,首先获取和表的笛卡尔积,然后通过具有匹配和字段的那些进行过滤.虽然完全不受约束的产品不存在于存储器中的任何地方,但仅存在一段时间,但其计算确实需要一些时间.people
companies
companyID
id
更好的方法是将约束与JOIN
相关的s 进行分组.这不仅在主观上更容易阅读,而且效率更高.正是如此:
SELECT * FROM people p JOIN companies c ON p.companyID = c.id WHERE p.firstName = 'Daniel'
它有点长,但数据库能够查看该ON
子句并使用它来JOIN
直接计算完全约束,而不是从所有内容开始然后限制.这样计算速度更快(特别是对于大型数据集和/或多表连接)并且需要更少的内存.
我改变了我看到的每个使用"逗号JOIN
"语法的查询.在我看来,它存在的唯一目的是简洁.考虑到性能影响,我认为这不是一个令人信服的理由.
INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN
用于连接的ANSI SQL/92语法越详细.对我来说,这种冗长使得连接对于开发者/ DBA更加清楚了解连接的意图.
在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)
所以,简短的回答 - 不需要重写,除非你每次维护它们都花了很长时间试图阅读它们?
它更像是一种语法选择.我更喜欢将连接条件与我的连接分组,因此我使用INNER JOIN语法
SELECT a.someRow, b.someRow FROM tableA AS a INNER JOIN tableB AS b ON a.ID = b.ID WHERE b.ID = ?
(?作为占位符)