[英]Weird Result From a MySql Query
I have three tables: 我有三个表:
I want to select all the posts that the user wrote from the posts table and the posts written by his friends specified by the friends table, I wrote this query: 我想从用户表中选择用户写的所有信息,以及由朋友表指定的他的朋友所写的信息,我编写了这个查询:
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'))
this gives me the posts written by his friends with many extra rows that I don't know where it came from. 这给了我他的朋友写的帖子,还有很多行,我不知道它来自哪里。 So can anybody tell me where is the problem here in the query?
那么有人可以告诉我查询中的问题在哪里吗?
Personally I think using that type of select syntax (SELECT ... FROM table1, table2, table3) is a little confusing to read and I wouldn't doubt it if you see some weird behavior because of it. 我个人认为使用这种类型的选择语法(SELECT ... FROM table1,table2,table3)有点令人困惑,并且如果您看到一些奇怪的行为,我也不会怀疑。 How about this instead:
怎么样呢:
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
I would write it this way. 我会这样写。
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'
If you use IN
, there's no need of nesting join friends table and users table: 如果使用
IN
,则不需要嵌套join friends表和users表:
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'
)
)
Your original query will return duplicate rows because you join to friends table based on one to many relationship. 您的原始查询将返回重复的行,因为您基于一对多关系加入了Friends表。 You have two choice to change it.
您有两种选择来更改它。 One way is add distinct to your select statement.
一种方法是在您的选择语句中添加不同的内容。 The other way is using exists like this(If there are too many fiends for a user,
EXISTS
will be more efficient than IN
): 另一种方法是使用像这样的存在(如果对用户有太多的恶魔,则
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'
I was able to solve my problem using nested SELECT statement: 我能够使用嵌套的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)
))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.