使用交叉联接和在两个表之间放置逗号有什么区别?
有什么区别
select * from A, B
和 和
select * from A cross join B
?他们似乎返回相同的结果。
第二个版本是否优于第一个版本?第一个版本在语法上完全错误吗?
What is the difference between
select * from A, B
and
select * from A cross join B
? They seem to return the same results.
Is the second version preferred over the first? Is the first version completely syntactically wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
它们返回相同的结果,因为它们在语义上是相同的。这是:
...是 (wince) SQL-89 语法。如果没有 WHERE 子句将表链接在一起,结果将是笛卡尔积。这正是替代方案所提供的:
...但是 CROSS JOIN 是 SQL-92 语法。
关于性能
它们之间没有性能差异。
为什么使用 SQL-92?
使用 SQL-92 语法的原因是为了支持 OUTER JOIN(即:LEFT、FULL、RIGHT)——SQL-89 语法没有任何语法,因此许多数据库实现了自己的语法(不移植到任何其他数据库) )。 IE:Oracle的
(+)
、SQL Server的=*
They return the same results because they are semantically identical. This:
...is (wince) SQL-89 syntax. Without a WHERE clause to link the tables together, the result is a Cartesian product. Which is exactly what alternative provides as well:
...but the CROSS JOIN is SQL-92 syntax.
About Performance
There's no performance difference between them.
Why Use SQL-92?
The reason to use SQL-92 syntax is for OUTER JOIN support (IE: LEFT, FULL, RIGHT)--SQL-89 syntax doesn't have any, so many databases implemented their own (which doesn't port to any other databases). IE: Oracle's
(+)
, SQL Server's=*
从另一个 SO 问题中偶然发现了这篇文章,但一个很大的区别是交叉连接创建的链接。例如,在第一个(“逗号”)变体上使用
cross apply
或B
之后的另一个联接,交叉应用或联接将仅引用点。例如,以下:会产生错误:
因为 C 上的联接仅适用于 B,而交叉联接也是如此...
.. 被认为是可以的。如果使用
cross apply
,同样适用。例如,在B
之后对函数进行交叉应用,该函数只能使用 B 的字段,而具有交叉联接的相同查询可以使用 A 和 B 中的字段。当然,这也意味着反过来也可以使用。如果您只想为其中一个表添加联接,可以通过在表上添加“逗号”来实现。
Stumbled upon this post from another SO question, but a big difference is the linkage cross join creates. For example using
cross apply
or another join afterB
on the first ('comma') variant, the cross apply or join would only refer to the table(s) after the dot. e.g, the following:would create an error:
because the join on C only scopes to B, whereas the same with cross join...
..is deemed ok. The same would apply if
cross apply
is used. For example placing a cross apply on a function afterB
, the function could only use fields of B, where the same query with cross join, could use fields from both A and B.Of course, this also means the reverse can be used as well. If you want to add a join solely for one of the tables, you can achieve that by going 'comma' on the tables.
除了简洁性(有利于
,
)和一致性(有利于CROSS JOIN
)之外,唯一的区别是优先级。逗号的优先级低于其他连接。
例如,
is
which 的显式形式是有效的。
which的显式形式
而is
是无效的(join 子句引用了不可访问的
a
)。在您的示例中,只有两个表,因此两个查询完全相同。
Besides brevity (favoring
,
) and consistency (favoringCROSS JOIN
), the sole difference is precedence.The comma is lower precedence than other joins.
For example, the explicit form of
is
which is valid.
Whereas the explicit form of
is
which is invalid (the join clause references inaccessible
a
).In your example, there are only two tables, so the two queries are exactly equivalent.
它们是相同的,并且(几乎)永远不应该使用。
They are the same and should (almost) never be used.
第一个版本最初是连接两个表的唯一方法。但它有很多问题,因此 ANSI-92 标准中添加了 JOIN 关键字。它们给出相同的结果,但第二个更明确并且是首选。
The first version was originally the only way to join two tables. But it has a number of problems so the JOIN keyword was added in the ANSI-92 standard. They give the same results but the second is more explicit and is to be preferred.
添加到已经给出的答案:
这是 1992 年 SQL 标准之前的唯一加入方式。因此,如果您想要内部联接,则必须使用
WHERE
子句作为条件:此语法的一个问题是外部联接没有标准。另一个问题是,这对于许多表来说是不可读的,因此容易出错且不易维护。
这里我们有 A 与 B/C/D 的交叉连接。有意还是无意?也许程序员只是忘记了
and B.id = A.id_b
(或其他什么),或者这行可能被错误地删除了,也许它仍然是真正的交叉连接。谁能说呢?这里与显式连接相同
不再怀疑程序员的意图。
旧的逗号分隔语法被替换是有充分理由的,不应再使用。
To add to the answers already given:
This was the only way of joining prior to the 1992 SQL standard. So if you wanted an inner join, you'd have to use the
WHERE
clause for the criteria:One problem with this syntax was that there was no standard for outer joins. Another was that this gets unreadable with many tables and is hence prone to errors and less maintainable.
Here we have a cross join of A with B/C/D. On purpose or not? Maybe the programmer just forgot the
and B.id = A.id_b
(or whatever), or maybe this line was deleted by mistake, and maybe still it was really meant to be a cross join. Who could say?Here is the same with explicit joins
No doubt about the programmers intentions anymore.
The old comma-separated syntax was replaced for good reasons and should not be used anymore.
这些是隐式和显式交叉连接的示例。请参阅http://en.wikipedia.org/wiki/Join_%28SQL%29#交叉连接。
These are the examples of implicit and explicit cross joins. See http://en.wikipedia.org/wiki/Join_%28SQL%29#Cross_join.
关于交叉联接的实用性的评论,有一个非常有用且有效的示例,在 Postgresgenerate_series 和 Postgis 空间 sql 的公认有点晦涩的世界中使用交叉联接或逗号,您可以在其中使用针对generate_series的交叉联接来提取几何图形集合或多(多边形/点/线串)中的第 n 个几何图形,请参阅:http://postgis.refractions.net/documentation/manual-1.4/ST_GeometryN.html
如果您想要获取面积、质心、边界框或您可以执行的许多其他操作,这可能非常有用当它们包含在一个更大的几何体中时,在单个几何体上。
我总是在generate_series之前使用逗号编写此类查询,直到有一天我想知道这是否真的意味着交叉连接,这让我看到了这篇文章。晦涩难懂,但绝对有用。
To the comments as to the utility of cross joins, there is one very useful and valid example of using cross joins or commas in the admittedly somewhat obscure world of Postgres generate_series and Postgis spatial sql where you can use a cross join against generate_series to extract the nth geometry out of a Geometry Collection or Multi-(Polygon/Point/Linestring), see: http://postgis.refractions.net/documentation/manual-1.4/ST_GeometryN.html
This can be very useful if you want to get the area, centroid, bounding box or many of the other operations you can perform on a single geometry, when they are contained within a larger one.
I have always written such queries using a comma before generate_series, until one day when I wondered if this really meant cross join, which brought me to this post. Obscure, but definitely useful.