如何处理您想要使用Left Join
的情况,因为数据可能存在也可能不存在。但是,如果Left Join
确实找到了一些数据,您是否希望通过在另一个表上加入左连接数据来进一步限制左连接数据? (不从结果中删除原始数据)。
我认为可能需要更多Join
,Where
或子查询。
这是我尝试的内容:
SELECT users.*, failed_logins.*
FROM users
LEFT JOIN failed_logins ON failed_logins.user_id = users.user_id
INNER JOIN banned ON banned.ip_address = failed_logins.ip_address
但如果banned
中没有匹配failed_logins
的数据,则会导致无法显示数据。
如果banned
中有匹配的行,我们希望包含banned
和failed_logins
中的行。否则,应排除failed_logins
和banned
的行。但是应该始终包含从users
抓取的数据。
答案 0 :(得分:2)
INNER JOIN中的条件将要求failed_logins.ip_address
具有非NULL值。将排除该列具有NULL值的任何行。而这将否定"外在性"联接到failed_logins
。 (users
中failed_logins
中没有匹配行的任何行,外部联接将从failed_logins
发明一个虚拟匹配行,匹配虚拟中的所有列row将为NULL。
因此,我们需要一种方法来返回NULL
的{{1}}值。
一种选择是使内连接成为外连接。也就是说,将failed_logins.ip_address
替换为INNER
。
还有其他一些方法可以解决此类问题。但这实际上取决于我们想要返回的结果集。示例数据和预期结果将大大有助于澄清规范。
修改
在重新阅读问题之后,我们仍然不清楚我们想要返回什么结果。为什么我们需要查看LEFT
表? "过滤数据(如果确实存在)"并没有真正解释说明书。
如果banned
中有匹配的行,我们希望从结果集中排除行?或者,我们希望返回banned
中不存在匹配行的行。
后续
首先在内联视图中使用banned
和failed_logins
之间的联接(或派生表以使用MySQL用语)。然后在banned
和派生表之间进行外连接。
举个例子:
users
给出SELECT users.*
, fl.*
FROM users
LEFT
JOIN ( SELECT f.user_id
, f.ip_address
FROM failed_logins f
JOIN banned b
ON b.ip_address = f.ip_address
) fl
ON fl.user_id = users.user_id
ORDER BY users.user_id, fl.ip_address
样本数据:
failed_logins
和 user_id ip_address
---------- ------------
111 127.0.0.1
111 192.168.0.1
222 127.0.0.1
333 192.168.0.1
444 4.4.4.4
示例数据
banned
并假设 ip_address
----------
127.0.0.1
包含五行,111到555,查询应返回:
users
如果这不符合规范,请考虑提供一些示例数据(包括应该和不应该返回的行的例子)以及预期的输出。