【问题标题】:INNER JOIN + LEFT JOIN (Double filtering)INNER JOIN + LEFT JOIN(双重过滤)
【发布时间】:2015-10-30 12:44:03
【问题描述】:

我正在尝试过滤我的表,其中用户在一个表中有一行,而在另一个表中没有一行。这是我的表结构:

这是一个 SQL Fiddle: http://sqlfiddle.com/#!9/6e27ed/2

CREATE TABLE users (
   user_id INT(11) AUTO_INCREMENT,
   name VARCHAR(25),
   PRIMARY KEY(user_id)
);

CREATE TABLE photos (
   photo_id INT(11) AUTO_INCREMENT,
   user_id INT(11) NOT NULL,
   PRIMARY KEY(photo_id)
);

CREATE TABLE blocked (
   user_id INT(11) NOT NULL,
   blocked_id INT(11) NOT NULL
);

INSERT INTO users (name) 
VALUES ('returned'), ('not returned'), ('not returned'), ('not returned');

INSERT INTO photos (user_id) 
VALUES (1), (2);

INSERT INTO blocked (user_id, blocked_id) 
VALUES (4, 2);

这是我正在尝试的查询:

SELECT u.*, min(p.photo_id)
FROM users u
INNER JOIN photos p using(user_id)
LEFT JOIN blocked b ON b.user_id = 4 AND b.blocked_id = u.user_id 
WHERE u.user_id != 4
GROUP BY u.user_id
LIMIT 9;

示例数据很明显应该是什么结果,因为在这个例子中“name”字段填充了"returned", "not returned",仍然返回了user-id 2,但是他应该被LEFT JOIN删除,因为用户 id 4 在阻塞表的阻塞 id 字段中有用户 id 2。

预期表格结果:

+---------+----------+-----------------+
| user_id |   name   | min(p.photo_id) |
+---------+----------+-----------------+
|       1 | returned |               1 |
+---------+----------+-----------------+

收到查询结果:

+---------+--------------+-----------------+
| user_id |     name     | min(p.photo_id) |
+---------+--------------+-----------------+
|       1 | returned     |               1 |
|       2 | not returned |               2 |
+---------+--------------+-----------------+

【问题讨论】:

    标签: mysql left-join


    【解决方案1】:

    我看到你在比较blocked_id=user_id 很难回答这个问题,尽管在blocked 表中你也有一个user_id 列。只有你自己知道。

    但请考虑以下内容

    SELECT u.*, min(p.photo_id),b.*
    FROM users u
    INNER JOIN photos p using(user_id)
    LEFT JOIN blocked b ON b.user_id = 4 AND b.blocked_id = u.user_id 
    WHERE u.user_id != 4 and b.user_id is null
    GROUP BY u.user_id
    LIMIT 9;
    
    +---------+----------+-----------------+---------+------------+
    | user_id | name     | min(p.photo_id) | user_id | blocked_id |
    +---------+----------+-----------------+---------+------------+
    |       1 | returned |               1 |    NULL |       NULL |
    +---------+----------+-----------------+---------+------------+
    

    它通过显示作为第 4 列和第 5 列添加的 b.* 列来打开声纳。并且有点与 where 子句混淆。

    编辑

    为生产清理

    SELECT u.*, min(p.photo_id)
    FROM users u
    INNER JOIN photos p using(user_id)
    LEFT JOIN blocked b ON b.user_id = 4 AND b.blocked_id = u.user_id 
    WHERE u.user_id != 4 and b.user_id is null
    GROUP BY u.user_id
    LIMIT 9;
    

    【讨论】:

    • blocked_id = u.user_id 用于检查当前正在检查的用户是否被选定用户阻止(在这种情况下为4)。如果不透露b.* 列,就没有办法做到这一点吗?这不是一个大问题,但它有点讨厌。
    • 我把它们放在那里展示它。当您使用它进行生产时,它们不属于结果集中!所以在where 中使用 em,不要在命令的第 1 行显示 em。
    【解决方案2】:

    我认为您希望WHERE b.blocked_id IS NULL 返回未被用户 4 阻止的用户

    【讨论】:

      【解决方案3】:

      你可以试试这个..

      SELECT u.*, min(p.photo_id)
      FROM users u
      INNER JOIN photos p using(user_id)
      LEFT JOIN blocked b ON b.blocked_id = u.user_id 
      GROUP BY u.user_id having min(p.photo_id)<=all(select min(p.photo_id) FROM users u
      INNER JOIN photos p using(user_id)
      LEFT JOIN blocked b ON b.blocked_id = u.user_id 
      GROUP BY u.user_id)
      ;
      

      【讨论】:

        猜你喜欢
        • 2018-07-10
        • 1970-01-01
        • 2013-02-07
        • 1970-01-01
        • 1970-01-01
        • 2019-09-03
        • 2015-03-03
        • 2012-08-17
        • 2014-03-11
        相关资源
        最近更新 更多