左连接不会返回第一个表的所有结果

时间:2017-11-09 16:14:36

标签: sql left-join

我有一个用于参考(数字)的表,如下所示

--------------------------
Id | User_Id | Number_Id |
--------------------------
1    400      1
2    400      2

然后另一个表(user_number)引用这些值,但是对于特定用户

SELECT n.Id, n.Name, n.Description, un.Id As Active_Number
FROM number n
LEFT JOIN user_number un
ON n.Id = un.Id
WHERE un.User_Id = 400;

我想要检索第一个表的所有结果,但我想看看它们在哪里匹配。我试图使用以下查询但它只返回INNER JOIN将返回的内容

[
    {
        "Id": 1,
        "Name": "One",
        "Description": "The number one",
        "Active_Number": 1
    },
    {
        "Id": 2,
        "Name": "Two",
        "Description": "The number two",
        "Active_Number": 2
    }
]

此查询返回:

RandomAccessFile dat = new RandomAccessFile("training\\"+lastTraining+".dat","rw");

但是,这并不会从数字表中返回第三组值。

6 个答案:

答案 0 :(得分:2)

不要'知道你正在使用什么数据库,但尝试

SELECT n.Id, n.Name, n.Description, un.Id As Active_Number
FROM number n
LEFT JOIN user_number un
ON n.Id = un.Id and un.User_Id = 400;

答案 1 :(得分:2)

您的WHERE条款将其变为INNER JOIN。把它放在ON子句中代替:

SELECT n.Id, n.Name, n.Description, un.Id As Active_Number
FROM number n
LEFT JOIN user_number un
ON n.Id = un.Id
AND un.User_Id = 400;

答案 2 :(得分:2)

因为在您的where条件中,您正在删除用户ID不是400的所有记录 - 这将排除左表中的任何行,但不包括右表。

根据where条件的位置,您将在连接之后将该过滤器应用于整个查询。你应该改为:

SELECT n.Id, n.Name, n.Description, un.Id As Active_Number
FROM number n
LEFT JOIN (select * from user_number 
WHERE un.User_Id = 400 ) un
ON n.Id = un.Id;
编辑:另一个响应者的回答是更好的选择,当我输入这段代码时,我没有选择 - 这也是有效的,但不是理想的解决方案。

答案 3 :(得分:1)

您的LEFT JOIN 会从第一个表中返回所有结果。这是LEFT JOIN

的结果
-------------------------------------------------------
Id | Name | Description     | Id | User_Id | Number_Id |
-------------------------------------------------------
1    One    The number one    1    400       1
2    Two    The number two    2    400       2
3    Three  The number three  NULL NULL      NULL

在这里,如果您对User_Id = 400进行过滤,那么排除第三行的原因显而易见。

查看这些结果时的常见建议是将过滤器更改为WHERE User_Id IS NULL OR User_Id = 400不要这样做。

假设您的第二个表中有其他记录使用不同的用户ID,因此左连接结果如下所示:

-------------------------------------------------------
Id | Name | Description     | Id | User_Id | Number_Id |
-------------------------------------------------------
1    One    The number one    1    400       1
2    Two    The number two    2    400       2
2    Two    The number two    3    500       2
3    Three  The number three  4    500       3

在这里,显而易见的是,你要删除最后一行。

您收到的有关将WHERE条件移至连接条件的其他答案将有效,但更合乎逻辑的IMO方法是使用子查询:

SELECT n.Id, n.Name, n.Description, un.Id As Active_Number
FROM number n
LEFT JOIN (
    SELECT *
    FROM user_number
    WHERE user_id = 400
) AS un
ON n.Id = un.Id;

这会将您加入的数据集减少到仅实际要加入的数据。但结果与将user_id = 400检查放入连接条件相同。

答案 4 :(得分:0)

始终将连接条件放在on子句中如果要进行内部连接,那么不要在on子句中添加任何where条件,将它们放在where子句中

如果您正在执行左连接,请在连接右侧的表的on子句中添加任何where条件。这是必须的,因为添加引用连接右侧的where子句会将连接转换为内连接(下面描述了一个例外)。

{{1}}

答案 5 :(得分:0)

删除WHERE条件,它将按预期工作。你正在做的基本上是正确地获得左连接,然后过滤掉第3行。

如果您想获得所有3个结果,您可以这样做:

SELECT n.Id, n.Name, n.Description, un.Id As Active_Number
FROM number n
LEFT JOIN user_number un
ON n.Id = un.Id
WHERE u.Id < 4;

换句话说,您应该过滤的表是左连接(数字)左侧的表。