我有三张桌子:
我想选择用户在posts表中写的所有帖子以及朋友表指定的朋友写的帖子,我写了这个查询:
SELECT
posts.ID as ID,
CONCAT(users.FirstName, ' ', users.LastName) as Name,
posts.Date as Date,
posts.Text as Text
FROM users, posts, friends
WHERE users.ID = posts.UserID AND
((posts.UserID = friends.ID1 AND friends.ID2 = '10000007') OR
(posts.UserID = friends.ID2 AND friends.ID1 = '10000007')
OR (posts.UserID = '10000007'))
这给了我朋友写的帖子,里面有许多额外的行,我不知道它来自哪里。那么有人能告诉我查询中的问题在哪里吗?
答案 0 :(得分:1)
就我个人而言,我认为使用这种类型的选择语法(SELECT ... FROM table1,table2,table3)有点令人困惑,如果你看到一些奇怪的行为,我就不会怀疑它。怎么样呢:
SELECT DISTINCT
posts.ID as ID,
CONCAT (users.FirstName, ' ', users.LastName) as Name,
posts.Date as Date,
posts.Text as Text
FROM
users
LEFT JOIN posts ON users.ID = posts.UserID
LEFT JOIN friends ON (
(posts.UserID = friends.ID1 AND friends.ID2 = '10000007') OR
(posts.UserID = friends.ID2 AND friends.ID1 = '10000007'))
HAVING
posts.UserID IS NOT NULL OR friends.ID1 IS NOT NULL
答案 1 :(得分:1)
我会这样写。
SELECT posts.ID as ID,
CONCAT(users.FirstName, ' ', users.LastName) as Name,
posts.Date as Date,
posts.Text as Text
FROM users
LEFT JOIN posts
ON users.ID = posts.UserID
OR posts.UserID IN
(SELECT ID2 FROM friends WHERE ID1 = '10000007'
UNION
SELECT ID1 FROM friends WHERE ID2 = '10000007')
WHERE users.ID = '10000007'
答案 2 :(得分:1)
如果您使用IN
,则无需嵌套加入好友表和用户表:
SELECT
posts.ID as ID,
users.ID as UserID,
CONCAT(users.FirstName, ' ', users.LastName) as Name,
posts.Date as Date,
posts.Text as Text
FROM users, posts -- Try to change the old style join to
-- FROM users JOIN posts
-- ON users.ID = posts.UserID Where ...
WHERE users.ID = posts.UserID
AND (posts.UserID = '10000007' OR
posts.UserID IN
(
SELECT ID
FROM friends
WHERE friends.ID1 = '10000007'
UNION
SELECT ID
FROM friends
WHERE friends.ID2 = '10000007'
)
)
您的原始查询将返回重复的行,因为您根据一对多关系加入了朋友表。你有两个选择来改变它。一种方法是在select语句中添加distinct。另一种方式是使用这样的存在(如果用户有太多恶魔,EXISTS
将比IN
更有效率:
SELECT
posts.ID as ID,
CONCAT(users.FirstName, ' ', users.LastName) as Name,
posts.Date as Date,
posts.Text as Text
FROM users
JOIN posts
ON users.ID = posts.UserID
WHERE
EXISTS
(SELECT 1
FROM friends
(posts.UserID = friends.ID1 AND friends.ID2 = '10000007')
OR
(posts.UserID = friends.ID2 AND friends.ID1 = '10000007')
)
OR posts.UserID = '10000007'
答案 3 :(得分:0)
我能够使用嵌套的SELECT语句解决我的问题:
SELECT
posts.ID as ID,
users.ID as UserID,
CONCAT(users.FirstName, ' ', users.LastName) as Name,
posts.Date as Date,
posts.Text as Text
FROM users, posts
WHERE users.ID = posts.UserID AND
(posts.UserID = '10000007' OR
posts.UserID IN (
SELECT users.ID
FROM users, friends
WHERE (friends.ID1 = '10000007' AND users.ID = friends.ID2)
OR (friends.ID2 = '10000007' AND users.ID = friends.ID1)
))