2010-04-18 124 views
0

哪个更好,有什么区别?SQL Select查询

SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B B) 

SELECT * FROM TABLE_A A, TABLE_B B WHERE A.ID = B.ID 
+0

第二个查询会起作用吗? – 2010-04-18 00:51:24

+1

@Mahesh Velaga:是的,从a,b'开始'是交叉连接b'的旧样式。对于'a'中的每一行,选择'b'中的所有行。所以'从a,b where a.id = b.id'等同于'从a.id = b.id'的内部连接b'# – Andomar 2010-04-18 01:02:20

+0

@Andomar:谢谢!直到这个较旧的版本兼容哪一点? – 2010-04-18 01:11:58

回答

9

“最佳” 的方式是使用标准的ANSI JOIN语法:

SELECT (columns) 
FROM TABLE_A a 
INNER JOIN TABLE_B b 
    ON b.ID = a.ID 

第一WHERE IN版本将经常结果在相同的执行计划,但在某些平台上它可能会变慢 - 它并不总是一致的。当您开始添加更多表或创建更复杂的连接条件时,IN查询(相当于EXISTS)在编写和维护时也变得越来越麻烦 - 它不如实际的JOIN那样灵活。

第二,逗号分隔的语法不如JOIN一贯支持。它在大多数SQL DBMS上都能正常工作,但它不是“首选”版本,因为如果你忽略了WHERE子句,那么你最终会得到一个交叉产品。而如果你忘记写在JOIN的条件下,你最终会出现语法错误。由于此安全网,倾向于优先选择JOIN

+0

+1用于指定列而不是'*'(更好的性能),我希望我可以给你另外一个+1明确指定JOIN ... – CJM 2010-04-18 01:07:35

+0

+1,但在单独的答案中查看我的意见。 – 2010-04-18 01:38:23

+0

这是一个很好的答案,但是以逗号分隔的语法(这是标准SQL的核心部分和此类功能可能永远不会从SQL标准中删除)的说法并不被广泛支持,这只是不真实的。我甚至会说它是CROSS JOIN语法更广泛的支持。只需编辑答案。 也考虑到这个问题,强调查询不一定会返回相同的结果(如http://stackoverflow.com/questions/2660666/sql-select-queries/2661058#2661058) – Unreason 2010-04-19 08:25:43

1

区别在于第一个子查询可能在某些数据库中速度较慢。第二个是连接,在同一个查询中组合两个表。

通常,如果数据库不会对其进行优化,则第二种方法会更快,因为使用子查询时数据库必须将子查询的结果保留在内存中。

3

我upvoted @ Aaronaught的答案,但我有一些意见:

  • 两个逗号式连接语法和句法JOIN是ANSI。第一个是SQL-89,第二个是SQL-92。 SQL-89语法仍然是标准的一部分,以支持向后兼容性。

  • 你能给出一个支持SQL-92语法但不支持SQL-89的RDBMS的例子吗?我不认为有任何,所以“不一致支持”可能不准确。

  • 您还可以使用JOIN语法省略连接条件,并创建笛卡尔积。例如:SELECT ... FROM A JOIN B是有效的(更正:仅在一些松散地实现标准语法的品牌(例如MySQL)中才是如此)。

    但是无论如何,我同意当你使用SQL-92语法时,这很容易被发现。如果使用SQL-89语法,则最终可能会生成一条长WHERE子句,并且很容易错过其中一个加入条件。

+0

'SELECT ... FROM A JOIN B'无效。 JOIN,没有限定默认为内部联接,并且需要ON子句。要得到一个笛卡尔积,你必须说:'SELECT ... FROM CROSS JOIN B'(可能有一些平台允许'JOIN'没有ON,但不是标准的。) – 2010-04-18 03:36:50

+0

@Shannon:是的,再右吧。 'JOIN'必须有'ON'或'USING'子句 - *除非你使用'NATURAL'或'UNION'加入修饰符。 – 2010-04-18 04:04:35

+0

Bill:我似乎记得回到SQL Server 2000中,如果您尝试使用SQL-89语法外连接视图,将会出现错误(“在包含外连接运算符的查询中无法指定连接的表”)。这是一个奇怪的和神秘的错误,通过切换到SQL-92连接来解决。尽管SQL-89仍然是一个标准,但我们都知道一些标准倾向于跨平台实现。 :)无论如何好点。 – Aaronaught 2010-04-18 07:37:57

1

这两个查询返回不同的结果。您只能从第一个TABLE_A中选择列。

1

有查询X之间至少三个不同之处:

SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B B) 

和Y:

SELECT * FROM TABLE_A A, TABLE_B B WHERE A.ID = B.ID 

1)正如Michas说,该组列的将是不同的,其中,查询ÿ将返回表A & B中的列,但查询X只返回表A中的列。如果明确指定了您想返回的列,则查询X只能包含来自表A的列,但查询Y将包括来自表A的列le B.

2)行数可能不同。如果表B具有比ID匹配从表A中的ID越多,那么更多的行将与查询y为返回比X.

create table TABLE_A (ID int, st VARCHAR(10)) 
create table TABLE_B (ID int, st VARCHAR(10)) 

insert into TABLE_A values (1, 'A-a') 

insert into TABLE_B values (1, 'B-a') 
insert into TABLE_B values (1, 'B-b') 

SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B B) 

ID   st 
----------- ---------- 
1   A-a 
(1 row(s) affected) 

SELECT * FROM TABLE_A A, TABLE_B B WHERE A.ID = B.ID 

ID   st   ID   st 
----------- ---------- ----------- ---------- 
1   A-a  1   B-a 
1   A-a  1   B-b 
(2 row(s) affected) 

3)执行计划可能会有所不同,因为查询询问数据库为不同的结果。 Inner joins用于运行速度超过inexists,并且在某些情况下仍可能运行得更快。 但由于结果可能不同,因此您需要确保数据支持从inexistsjoin的转换。

+0

+1,但重新3)取决于a.id和b.id之间的关系,你可能是对的,也可能不是;在一对一或一对一的情况下或在多对一或一对多关系的情况下,查询将最有可能产生相同的计划(查询要求相同的结果)以防一对一 - 多或多对它不会。这取决于。 – Unreason 2010-04-19 08:20:50