来自MySql查询的奇怪结果

时间:2014-11-01 05:09:25

标签: mysql sql

我有三张桌子:

  1. 用户(所有用户)
  2. 朋友(关系表由ID1和ID2列组成,基本上可以告诉谁的朋友)
  3. 帖子(所有帖子都包含已写入用户的ID)。
  4. 我想选择用户在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'))
    

    这给了我朋友写的帖子,里面有许多额外的行,我不知道它来自哪里。那么有人能告诉我查询中的问题在哪里吗?

4 个答案:

答案 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)
))