查询隐式SQL连接不能做什么?

时间:2009-12-30 18:12:42

标签: sql join

我从来没有学过联接是如何工作的,只是使用select和where子句已经足够我所做的所有查询。是否有使用WHERE子句无法获得正确结果的情况,我必须使用JOIN?如果是这样,有人可以提供例子吗?感谢。

7 个答案:

答案 0 :(得分:8)

隐式联接超过20年已过时。为什么你会考虑用它们编写代码?

是的,他们可以创建显式联接没有的问题。说到SQL Server,左右连接隐式语法不能保证返回正确的结果。有时,它们返回交叉连接而不是外连接。这是件坏事。甚至至少回到SQL Server 2000也是如此,并且它们正在逐步淘汰,所以使用它们是一种全面的糟糕做法。

隐式连接的另一个问题是,忘记其中一个where条件很容易意外地进行交叉连接,特别是当你加入太多表时。通过使用显式连接,如果您忘记放入连接条件并且必须明确指定交叉连接,则会出现语法错误。同样,这会导致查询返回不正确的值,或者通过使用distinct来解决,以消除最好效率低下的交叉连接。

此外,如果您有交叉连接,那么在一年内进行更改的维护开发人员在使用隐式连接时不知道是否有意。

我相信一些ORM现在也需要明确的连接。

此外,如果您使用隐含连接是因为您不了解连接的运行方式,那么您编写的代码实际上可能无法返回正确的结果,因为您不知道如何评估正确的结果将是因为你不明白连接的意图。

如果你编写任何风格的SQL代码,没有理由不彻底理解联接。

答案 1 :(得分:3)

是。在做外连接时。您可以在联接上阅读this simple article。加入并不难理解,所以你应该立即开始学习(并在适当的时候使用它们)。

答案 2 :(得分:2)

  

是否存在使用WHERE子句无法获得正确结果的情况,我必须使用JOIN?

只要您的查询涉及两个或更多表,就会使用连接。 This link非常适合显示图片和样本结果集的连接差异。

如果连接条件在WHERE子句中,则使用ANSI-89 JOIN语法。 ANSI-92格式中较新的JOIN语法的原因在于它使LEFT JOIN在各种数据库中更加一致。例如,Oracle在可选的一侧使用(+),而在SQL Server中则必须使用=*

答案 3 :(得分:0)

如果您想要合并两个表的结果,您需要加入它们。举个例子:

用户表:

ID
FirstName
LastName
UserName
Password

和地址表:

ID
UserID
AddressType (residential, business, shipping, billing, etc)
Line1
Line2
City
State
Zip

单个用户可以列出他的住所和他的公司地址(或运输和账单地址),或者根本没有地址。使用简单的WHERE子句不会获取没有地址的用户,因为地址位于不同的表中。为了立即获取用户的地址,您需要进行以下连接:

SELECT *
FROM Users
LEFT OUTER JOIN Addresses
    ON Users.ID = Addresses.UserID
WHERE Users.UserName = "foo"

请参阅http://www.w3schools.com/Sql/sql_join.asp,了解不同联接的更深入定义及其工作原理。

答案 4 :(得分:0)

默认情况下,隐式连接语法使用内部连接。有时可以修改隐式连接语法来指定外连接,但根据我的经验,它依赖于供应商(我知道oracle有( - )和(+)表示法,我相信sqlserver使用* =)。所以,我相信你的问题可以归结为理解内部和外部联接之间的差异。

我们可以使用简单的查询来查看内部连接和外部连接的简单示例..........

隐含的INNER联接:

select a.*, b.*
from table a, table b
where a.id = b.id;

上面的查询将仅返回'a'行在'b'中为其'id'字段匹配行的行。

显式OUTER JOIN:

select * from
table a LEFT OUTER JOIN table b
on a.id = b.id;

上面的查询将带回a中的每一行,无论它是否在'b'中有匹配的行。如果'b'不存在匹配,则'b'字段将为空。

在这种情况下,如果你想将'a'中的每一行都带回来,无论它是否有相应的'b'行,你都需要使用外连接。

就像我说的,根据您的数据库供应商,您仍然可以使用隐式连接语法并指定外部连接类型。但是,这会将您与该供应商联系起来。此外,任何不熟悉专业语法的开发人员可能难以理解您的查询。

答案 5 :(得分:0)

使用联接:

SELECT a.MainID, b.SubValue AS SubValue1, b.SubDesc AS SubDesc1, c.SubValue AS SubValue2, c.SubDesc AS SubDesc2
FROM MainTable AS a
LEFT JOIN SubValues AS b ON a.MainID = b.MainID AND b.SubTypeID = 1
LEFT JOIN SubValues AS c ON a.MainID = c.MainID AND b.SubTypeID = 2

副手,我看不到通过使用简单的WHERE子句来连接表获得相同结果的方法。 此外,WHERE子句中常用于左右连接(* =和= *)的语法正在逐步淘汰,

答案 6 :(得分:0)

Oracle 使用其特殊的连接运算符 LEFT JOIN 支持 RIGHT JOIN(+)(并且 SQL Server 曾经在连接谓词上支持 *==*,但没有更长的时间)。但是一个简单的 FULL JOIN 不能单独使用隐式连接:

SELECT f.title, a.first_name, a.last_name
FROM film f
FULL JOIN film_actor fa ON f.film_id = fa.film_id
FULL JOIN actor a ON fa.actor_id = a.actor_id

这会生成所有电影及其演员,包括所有没有演员的电影,以及没有电影的演员。要仅使用隐式连接来模拟这一点,您需要联合。

-- Inner join part
SELECT f.title, a.first_name, a.last_name
FROM film f, film_actor fa, actor a
WHERE f.film_id = fa.film_id
AND fa.actor_id = a.actor_id

-- Left join part
UNION ALL
SELECT f.title, null, null
FROM film f
WHERE NOT EXISTS (
  SELECT 1
  FROM film_actor fa
  WHERE fa.film_id = f.film_id
)

-- Right join part
UNION ALL
SELECT null, a.first_name, a.last_name
FROM actor a
WHERE NOT EXISTS (
  SELECT 1
  FROM film_actor fa
  WHERE fa.actor_id = a.actor_id
)

这将很快在语法和性能方面变得非常低效。