SQL内部联接语法
下面的两位SQL得到相同的结果SQL内部联接语法,sql,syntax,inner-join,cross-join,Sql,Syntax,Inner Join,Cross Join,下面的两位SQL得到相同的结果 SELECT c.name, o.product FROM customer c, order o WHERE c.id = o.cust_id AND o.value = 150 SELECT c.name, o.product FROM customer c INNER JOIN order o on c.id = o.cust_id WHERE o.value = 150 我见过这两种风格在不同的公司被作为标准。据我所见,第二
SELECT c.name, o.product
FROM customer c, order o
WHERE c.id = o.cust_id
AND o.value = 150
SELECT c.name, o.product
FROM customer c
INNER JOIN order o on c.id = o.cust_id
WHERE o.value = 150
我见过这两种风格在不同的公司被作为标准。据我所见,第二个是大多数人在网上推荐的。除了风格之外,还有什么真正的原因吗?使用内部联接有时会有更好的性能吗
我注意到安格尔和Oracle开发人员倾向于使用第一种风格,而Microsoft SQL Server用户倾向于使用第二种风格,但这可能只是巧合
谢谢你的见解,我想知道这一点已经有一段时间了
编辑:由于使用了不正确的术语,我将标题从“SQL内部联接与笛卡尔积”更改为“SQL内部联接与笛卡尔积”。感谢到目前为止的所有回复。两个查询都在执行内部联接,只是语法不同。实际上,这些示例是等效的,两者都不是笛卡尔积。当您在不指定联接条件的情况下联接两个表时,将返回笛卡尔积,例如
select *
from t1,t2
关于这一点,我们进行了很好的讨论。为了回答您的部分问题,我认为早期的bug在加入。。。Oracle中的ON语法不鼓励Oracle用户使用该语法。我认为现在没有什么特别的问题
它们是等价的,应该解析为相同的内部表示形式以进行优化 Oracle支持加入的时间较晚。。。关于(ANSI)语法(直到Oracle 9),这就是Oracle开发人员经常不使用它的原因 就我个人而言,当逻辑上很清楚一个表驱动查询,而其他表是查找表时,我更喜欢使用ANSI语法。当表“相等”时,我倾向于使用笛卡尔语法
性能应该不会有任何不同。两个查询都是内部连接,并且是等效的。第一种是较旧的操作方法,而连接语法的使用只是在引入SQL-92标准后才变得普遍(我相信这是在较旧的定义中,只是在此之前没有得到特别广泛的使用) 强烈推荐使用连接语法,因为它将连接逻辑与WHERE子句中的过滤逻辑分离。虽然连接语法实际上是内部连接的语法糖,但它的优势在于外部连接,在这种情况下,旧的*语法可能会产生无法明确描述连接的情况,并且解释依赖于实现。[LEFT | RIGHT]JOIN语法避免了这些缺陷,因此为了保持一致性,最好在所有情况下都使用JOIN子句 请注意,这两个示例都不是笛卡尔积。你也可以用这两种方法
SELECT c.name, o.product
FROM customer c, order o
WHERE o.value = 150
或
加入。。。在…上语法是ANSI和ISO SQL规范的最新补充。加入。。。在…上语法通常是首选的,因为它1)将连接条件移出WHERE子句,使WHERE子句仅用于过滤;2)如果您正在创建一个可怕的笛卡尔积,则它会更明显,因为每个连接必须至少伴随一个ON子句。如果WHERE子句中的所有连接条件都是AND,那么当缺少一个或多个连接条件时,情况就不那么明显了。TL;博士 内部联接语句可以重写为交叉联接,其中WHERE子句与内部联接查询的ON子句中使用的条件相同 表关系 考虑到我们有以下
post
和post\u comment
表格:
post
具有以下记录:
| id | title |
|----|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
而post_comment
有以下三行:
| id | review | post_id |
|----|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
SQL内部联接
SQL JOIN子句允许您关联属于不同表的行。例如,a将创建一个笛卡尔积,其中包含两个连接表之间所有可能的行组合
虽然交叉联接在某些情况下很有用,但大多数情况下,您希望根据特定条件联接表。这就是内部连接发挥作用的地方
SQL内部联接允许我们根据通过on子句指定的条件过滤联接两个表的笛卡尔积
SQL内部联接-在“始终为真”条件下
如果提供“始终为真”条件,内部联接将不会过滤联接的记录,结果集将包含两个联接表的笛卡尔积
例如,如果执行以下SQL内部联接查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
我们将获得post
和post\u comment
记录的所有组合:
| p.id | pc.id |
|---------|------------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
因此,如果ON子句条件为“always true”,则内部连接仅等效于交叉连接查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
SQL内部联接-在“始终为false”条件下
另一方面,如果On子句条件为“always false”,则所有连接的记录都将被过滤掉,结果集将为空
因此,如果我们执行以下SQL内部联接查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
我们不会得到任何结果:
| p.id | pc.id |
|---------|------------|
这是因为上面的查询相当于以下交叉连接查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
使用外键列和主键列的SQL内部JOIN-ON子句
最常见的ON子句条件是将子表中的外键列与父表中的主键列相匹配的条件,如以下查询所示:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id
执行上述SQL内部联接查询时,我们得到以下结果集:
| p.id | pc.post_id | pc.id | p.title | pc.review |
|---------|------------|------------|------------|-----------|
| 1 | 1 | 1 | Java | Good |
| 1 | 1 | 2 | Java | Excellent |
| 2 | 2 | 3 | Hibernate | Awesome |
因此,查询结果集中只包括与ON子句条件匹配的记录。在我们的例子中,结果集包含所有post
以及它们的post\u注释
记录。没有关联的post\u注释的post
行被排除在外,因为它们不能满足ON子句条件
同样,上述SQL内部联接查询相当于以下交叉联接查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
未删除的行是满足WHERE子句的行,只有这些记录才会包含在结果集中。这就是问题所在