SQL 连接实际上是如何工作的?
How the SQL join actually works?
假设我有两个 table Gardners table
和 Plantings table
.
假设我的查询是:
SELECT gid, first_name, last_name, pid, gardener_id, plant_name
FROM Gardners
INNER JOIN Plantings
ON gid = gardener_id
我想知道它在内部究竟是如何工作的?
根据我对每个 join
条件的理解:
Gardner Table
的每一行将与 Plantings Table
的每一行进行比较。如果条件匹配,那么它将打印出来。我的理解正确吗?
在程序方面如果你认为:
for i in [Gardners Table]:
for j in [Plantings Table]:
if i.id == j.garderner id:
print <>
现在假设您的查询是这样的:
User(uid,uname,ucity,utimedat)
Follows(uid,followerid) // uid and followerid are pointing to `uid` of `User`.
SELECT U.uid, U.uname FROM User U1 JOIN Follows F,User U2 WHERE
F.followerid = U2.uiddate AND U2.ucity = 'D'
这里的连接条件在内部是如何工作的?是否等同于:
for i in [USER]:
for j in [Follows]:
for k in [USER]:
if condition:
print <>
是的,如果您只是在谈论一个联接而不是另一个联接,那么您的理解是正确的,例如:内部,外部,如 SQL
您使用 Gardners table
和 Plantings table
的示例是正确的。但是 users
的例子并不那么明显。
我觉得你想得到的是某个城市的用户关注度。
假设正确的查询是:
SELECT U1.uid, U2.uname
FROM User U1
JOIN Follows F ON U1.uid = F.uid
JOIN User U2 ON F.followerid = U2.uid
WHERE U2.ucity = 'D'
然后在伪代码中它看起来像这样:
for i in [User Table]:
for j in [Follows Table]:
if i.uid = j.uid:
for k in [User Table]:
if j.followerid = k.uid and k.city = 'D':
print <>
SQL Fiddle 为此:http://sqlfiddle.com/#!9/caeb1e/5
可以在此处找到关于联接实际工作原理的非常好的图片:http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
在您的第二个查询中,由于语法错误,您不清楚您要做什么;但如果我猜的话,你的意图似乎是通过追随者 F 和用户 U2 之间的(隐式)连接的子查询来加入用户 U1。
如果我的猜测是正确的,查询应该更像这样:
SELECT U1.uid, U1.uname
FROM User U1 JOIN
(SELECT U2.uid
FROM Followers F,User U2
WHERE F.followerid = U2.uiddate AND U2.ucity = 'D') T
WHERE u1.uid = T.uid
这也不是 'best practice' 编写查询的方式(您应该使用显式连接,不需要子查询,但您可以连接三次,依此类推)
但我这样写是为了让它最接近您的原始查询。
如果我的猜测是正确的,那么你的伪代码将更像是:
for u2 in [User 2 where condition]:
for f in [Follows]:
if f.uid == u2.uid
SELECT uid AS T
for u1 in [User 1]:
if u1.uid == T.uid:
print <>
然而,这并不是一个完全解释的解释,因为理解 SQL 的一个关键是在 'set' 中更多地思考被过滤的数据,而不是数据对象的顺序选择,因为 SQL根据一组数据进行运算,大家可能不习惯。
所以上面的一些步骤将一次性执行,而不是顺序执行。但除此之外,您应该查看上面 Yuri Tkachenko 给出的关于如何查看连接的答案——然后在编写正确的连接时,内部结构将排在第二位。
假设我有两个 table Gardners table
和 Plantings table
.
假设我的查询是:
SELECT gid, first_name, last_name, pid, gardener_id, plant_name
FROM Gardners
INNER JOIN Plantings
ON gid = gardener_id
我想知道它在内部究竟是如何工作的?
根据我对每个 join
条件的理解:
Gardner Table
的每一行将与Plantings Table
的每一行进行比较。如果条件匹配,那么它将打印出来。我的理解正确吗?
在程序方面如果你认为:
for i in [Gardners Table]:
for j in [Plantings Table]:
if i.id == j.garderner id:
print <>
现在假设您的查询是这样的:
User(uid,uname,ucity,utimedat)
Follows(uid,followerid) // uid and followerid are pointing to `uid` of `User`.
SELECT U.uid, U.uname FROM User U1 JOIN Follows F,User U2 WHERE
F.followerid = U2.uiddate AND U2.ucity = 'D'
这里的连接条件在内部是如何工作的?是否等同于:
for i in [USER]:
for j in [Follows]:
for k in [USER]:
if condition:
print <>
是的,如果您只是在谈论一个联接而不是另一个联接,那么您的理解是正确的,例如:内部,外部,如 SQL
您使用 Gardners table
和 Plantings table
的示例是正确的。但是 users
的例子并不那么明显。
我觉得你想得到的是某个城市的用户关注度。
假设正确的查询是:
SELECT U1.uid, U2.uname
FROM User U1
JOIN Follows F ON U1.uid = F.uid
JOIN User U2 ON F.followerid = U2.uid
WHERE U2.ucity = 'D'
然后在伪代码中它看起来像这样:
for i in [User Table]:
for j in [Follows Table]:
if i.uid = j.uid:
for k in [User Table]:
if j.followerid = k.uid and k.city = 'D':
print <>
SQL Fiddle 为此:http://sqlfiddle.com/#!9/caeb1e/5
可以在此处找到关于联接实际工作原理的非常好的图片:http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
在您的第二个查询中,由于语法错误,您不清楚您要做什么;但如果我猜的话,你的意图似乎是通过追随者 F 和用户 U2 之间的(隐式)连接的子查询来加入用户 U1。
如果我的猜测是正确的,查询应该更像这样:
SELECT U1.uid, U1.uname
FROM User U1 JOIN
(SELECT U2.uid
FROM Followers F,User U2
WHERE F.followerid = U2.uiddate AND U2.ucity = 'D') T
WHERE u1.uid = T.uid
这也不是 'best practice' 编写查询的方式(您应该使用显式连接,不需要子查询,但您可以连接三次,依此类推) 但我这样写是为了让它最接近您的原始查询。
如果我的猜测是正确的,那么你的伪代码将更像是:
for u2 in [User 2 where condition]:
for f in [Follows]:
if f.uid == u2.uid
SELECT uid AS T
for u1 in [User 1]:
if u1.uid == T.uid:
print <>
然而,这并不是一个完全解释的解释,因为理解 SQL 的一个关键是在 'set' 中更多地思考被过滤的数据,而不是数据对象的顺序选择,因为 SQL根据一组数据进行运算,大家可能不习惯。 所以上面的一些步骤将一次性执行,而不是顺序执行。但除此之外,您应该查看上面 Yuri Tkachenko 给出的关于如何查看连接的答案——然后在编写正确的连接时,内部结构将排在第二位。