使用交叉联接和在两个表之间放置逗号有什么区别?

发布于 2024-09-27 00:50:30 字数 185 浏览 4 评论 0原文

有什么区别

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

赴月观长安 2024-10-04 00:50:30

它们返回相同的结果,因为它们在语义上是相同的。这是:

select * 
  from A, B

...是 (wince) SQL-89 语法。如果没有 WHERE 子句将表链接在一起,结果将是笛卡尔积。这正是替代方案所提供的:

    select * 
      from A 
cross join B

...但是 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:

select * 
  from A, B

...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:

    select * 
      from A 
cross join B

...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 =*

天暗了我发光 2024-10-04 00:50:30

从另一个 SO 问题中偶然发现了这篇文章,但一个很大的区别是交叉连接创建的链接。例如,在第一个(“逗号”)变体上使用 cross applyB 之后的另一个联接,交叉应用或联接将仅引用点。例如,以下:

select * from A, B join C on C.SomeField = A.SomeField and C.SomeField = B.SomeField 

会产生错误:

无法绑定多部分标识符“A.SomeField”。

因为 C 上的联接仅适用于 B,而交叉联接也是如此...

select * from A cross join B join C on C.SomeField = A.SomeField and C.SomeField = B.SomeField 

.. 被认为是可以的。如果使用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 after B on the first ('comma') variant, the cross apply or join would only refer to the table(s) after the dot. e.g, the following:

select * from A, B join C on C.SomeField = A.SomeField and C.SomeField = B.SomeField 

would create an error:

The multi-part identifier "A.SomeField" could not be bound.

because the join on C only scopes to B, whereas the same with cross join...

select * from A cross join B join C on C.SomeField = A.SomeField and C.SomeField = B.SomeField 

..is deemed ok. The same would apply if cross apply is used. For example placing a cross apply on a function after B, 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.

洋洋洒洒 2024-10-04 00:50:30

除了简洁性(有利于,)和一致性(有利于CROSS JOIN)之外,唯一的区别是优先级。

逗号的优先级低于其他连接。


例如,

SELECT *
FROM a
  CROSS JOIN b
  JOIN c ON a.id = c.id

is

SELECT *
FROM (
  a
  CROSS JOIN b
)
  INNER JOIN c ON a.id = c.id

which 的显式形式是有效的。

which的显式形式

SELECT *
FROM a,
  b
  JOIN c ON a.id = c.id

而is

SELECT *
FROM a
  CROSS JOIN (
    b
    INNER JOIN c ON a.id = c.id
  )

是无效的(join 子句引用了不可访问的 a)。


在您的示例中,只有两个表,因此两个查询完全相同。

Besides brevity (favoring ,) and consistency (favoring CROSS JOIN), the sole difference is precedence.

The comma is lower precedence than other joins.


For example, the explicit form of

SELECT *
FROM a
  CROSS JOIN b
  JOIN c ON a.id = c.id

is

SELECT *
FROM (
  a
  CROSS JOIN b
)
  INNER JOIN c ON a.id = c.id

which is valid.

Whereas the explicit form of

SELECT *
FROM a,
  b
  JOIN c ON a.id = c.id

is

SELECT *
FROM a
  CROSS JOIN (
    b
    INNER JOIN c ON a.id = c.id
  )

which is invalid (the join clause references inaccessible a).


In your example, there are only two tables, so the two queries are exactly equivalent.

回忆凄美了谁 2024-10-04 00:50:30

它们是相同的,并且(几乎)永远不应该使用。

They are the same and should (almost) never be used.

白馒头 2024-10-04 00:50:30

第一个版本最初是连接两个表的唯一方法。但它有很多问题,因此 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.

横笛休吹塞上声 2024-10-04 00:50:30

添加到已经给出的答案:

select * from A, B

这是 1992 年 SQL 标准之前的唯一加入方式。因此,如果您想要内部联接,则必须使用 WHERE 子句作为条件:

select * from A, B
where A.x = B.y;

此语法的一个问题是外部联接没有标准。另一个问题是,这对于许多表来说是不可读的,因此容易出错且不易维护。

select * from A, B, C, D
where B.id = C.id_b
and C.id_d = D.id;

这里我们有 A 与 B/C/D 的交叉连接。有意还是无意?也许程序员只是忘记了 and B.id = A.id_b (或其他什么),或者这行可能被错误地删除了,也许它仍然是真正的交叉连接。谁能说呢?

这里与显式连接相同

select * 
from A
cross join B
inner join C on C.id_b = B.id
inner join D on D.id = C.id_d;

不再怀疑程序员的意图。

旧的逗号分隔语法被替换是有充分理由的,不应再使用。

To add to the answers already given:

select * from A, B

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:

select * from A, B
where A.x = B.y;

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.

select * from A, B, C, D
where B.id = C.id_b
and C.id_d = D.id;

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

select * 
from A
cross join B
inner join C on C.id_b = B.id
inner join D on D.id = C.id_d;

No doubt about the programmers intentions anymore.

The old comma-separated syntax was replaced for good reasons and should not be used anymore.

神魇的王 2024-10-04 00:50:30

这些是隐式和显式交叉连接的示例。请参阅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.

巾帼英雄 2024-10-04 00:50:30

关于交叉联接的实用性的评论,有一个非常有用且有效的示例,在 Postgresgenerate_series 和 Postgis 空间 sql 的公认有点晦涩的世界中使用交叉联接或逗号,您可以在其中使用针对generate_series的交叉联接来提取几何图形集合或多(多边形/点/线串)中的第 n 个几何图形,请参阅:http://postgis.refractions.net/documentation/manual-1.4/ST_GeometryN.html

SELECT n, ST_AsEWKT(ST_GeometryN(the_geom, n)) As geomewkt
  FROM (
    VALUES (ST_GeomFromEWKT('MULTIPOINT(1 2 7, 3 4 7, 5 6 7, 8 9 10)') ),
          ( ST_GeomFromEWKT('MULTICURVE(CIRCULARSTRING(2.5 2.5,4.5 2.5, 3.5 3.5), (10 11, 12 11))') )
    )  As foo(the_geom)
CROSS JOIN generate_series(1,100) n
  WHERE n <= ST_NumGeometries(the_geom);

如果您想要获取面积、质心、边界框或您可以执行的许多其他操作,这可能非常有用当它们包含在一个更大的几何体中时,在单个几何体上。

我总是在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

SELECT n, ST_AsEWKT(ST_GeometryN(the_geom, n)) As geomewkt
  FROM (
    VALUES (ST_GeomFromEWKT('MULTIPOINT(1 2 7, 3 4 7, 5 6 7, 8 9 10)') ),
          ( ST_GeomFromEWKT('MULTICURVE(CIRCULARSTRING(2.5 2.5,4.5 2.5, 3.5 3.5), (10 11, 12 11))') )
    )  As foo(the_geom)
CROSS JOIN generate_series(1,100) n
  WHERE n <= ST_NumGeometries(the_geom);

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文