SQL子查询返回空值

4

对不起,标题可能不太好,但我没有找到更好的。 我的问题是: 我想从表“log”中选择所有字段,其中字段“user”为“user1”或“friendships”中的“user2”。我的查询看起来像这样,但它返回零值:

    SELECT * FROM `log` 
    WHERE `user` = ANY(SELECT `user1` FROM `friendships` 
                       WHERE (`user1` = 1 OR `user2` = 1) AND `active` = 1) 
    OR `user` = ANY(SELECT `user2` FROM `friendships` 
                    WHERE (`user1` = 1 OR `user2` = 1) AND `active` = 1) 
    GROUP BY `arguments` 
    ORDER BY `created` DESC

如果我只使用一个子查询,它可以工作,但我也需要第二个字段。而且有更多的值(这就是为什么我使用带有ANY的子查询而不是JOIN的原因)。 我希望有人能找到我的错误 :)。

2
这是什么数据库?Oracle? - DOK
@Bohemian:你改变了原始查询,而不仅仅是重新格式化它! - Andriy M
我“修改”了它,但执行结果完全相同。我将= ANY改为了IN,并将(user1 = 1 or user1 = 2)改为了user1 in (1, 2)...那又怎样呢?实际上,这样做的性能会更好。 - Bohemian
@Bohemian:不,最初是 user1 = 1 或 user2 = 1 - Andriy M
@Bohemian - 这确实更简洁,但对我来说也更难读懂。各有所好... - Lieven Keersmaekers
显示剩余4条评论
3个回答

3
我希望你能够成功:
SELECT *
FROM `log` INNER JOIN `friendships` on
    `log`.`user` = `friendships`.`user`
WHERE `friendships`.`user` in (1,2)
            AND
      `friendships`.`active` = 1
ORDER BY `created` DESC

PS: 你可以发表你的表格架构。

UPDATE 1

SELECT *
FROM
(
    SELECT *
    FROM `log` INNER `friendships` on
        `log`.`user` = `friendships`.`user1`
    WHERE `friendships`.`user1` in (1,2) 
            AND
          `friendships`.`active` = 1
    UNION
    SELECT *
    FROM `log` INNER `friendships` on
        `log`.`user` = `friendships`.`user2`
    WHERE `friendships`.`user2` in (1,2) 
            AND
          `friendships`.`active` = 1
) as iTable
ORDER BY iTable.`created` DESC

非常感谢您的帮助。发布的查询不起作用,因为我需要用户1和用户2(第2行和第3行)。我会搜索、阅读并尝试编辑查询以满足我的需求。结构在这里:http://nopaste.me/paste/6149289184f2157074c90c 对于链接我很抱歉,但我无法在此处使用代码标记。 - David
不,这不是我需要的。我的查询中的1(user1或user2必须是什么)是一个用户ID。用户ID不是静态的(只是使用test-user进行测试)。 - David
@user1141147,1和2可以替换为您的“userID”,您仍然可以进行修改。我已更新查询。 - John Woo
谢谢。第二个似乎是正确的,但我遇到了一个错误(MySQL):#1064-您的SQL语法有误,请检查与您的MySQL服务器版本相对应的手册,以获取正确的语法使用方式,在第5行附近的“friendships on log.user = friendships.user1 WHERE `frien” - David

1

我可能会尝试不同的方法,也许是这样:

SELECT *
FROM `log`
WHERE `user` IN (
  SELECT `user1` FROM `friendships` WHERE `user2` = @user AND `active` = 1

  UNION ALL

  SELECT `user2` FROM `friendships` WHERE `user1` = @user AND `active` = 1

  UNION ALL

  SELECT @user
)
GROUP BY
  `arguments`
ORDER BY
  `created` DESC

虽然实话实说,我会避免在这样的查询中选择既不聚合也不包含在GROUP BY中的列,即使MySQL允许我这样做。

另一种选择:

SELECT *
FROM `log`
WHERE `user` IN (
  SELECT
    CASE `user1` WHEN @user THEN `user2` ELSE `user1` END AS `user`
  FROM `friendships`
  WHERE (`user1` = @user OR `user2` = @user) AND `active` = 1

  UNION ALL

  SELECT @user
)
GROUP BY
  `arguments`
ORDER BY
  `created` DESC

1
谢谢。我找到了我的愚蠢错误。我想要每个找到的ID的值,这就是为什么它对我不起作用的原因。我用2个查询和UNION ALL解决了这个问题。 - David
感谢大家。IN语句是我需要的,当然UNION也很好用 :). - David

1

使用 union 将 OR 重构为单个列表:

select * 
from `log` 
where `user` in (
    select user1
    from friendships 
    where user1 in (1, 2) and active)
    union
    select user2
    from friendships 
    where `user1` in (1, 2) and active
)
group by arguments
order by `created` desc

或者在标准连接上使用联合

select * from (
select l.* 
from `log` l
join friendships f on l.user = f.user1 and f.user1 in (1, 2) and f.active
union
select l.* 
from `log` l
join friendships f on l.user = f.user2 and f.user2 in (1, 2) and f.active
) x
group by arguments
order by `created` desc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接