SQL LEFT JOIN 从第二个表中排除两条记录

Posted

技术标签:

【中文标题】SQL LEFT JOIN 从第二个表中排除两条记录【英文标题】:SQL LEFT JOIN EXCLUDE TWO RECORDS FROM SECOND TABLE 【发布时间】:2020-09-20 15:18:03 【问题描述】:

如果状态=是,我正在尝试左连接,并且还想从第二个表中排除记录。但是当我使用 LEFT join 时,它会给出 table1 中的所有记录,而不排除 table2 中状态为“是”的记录。

Table1
--------------------------------
id  date
--------------------------------
1   01/09/2020
2   02/09/2020
3   03/09/2020
4   04/09/2020
5   05/09/2020


Table2
--------------------------------
id  date          status
--------------------------------
1   01/09/2020    Yes
2   02/09/2020    Yes
3   03/09/2020

想要的结果

--------------------------------
id  date
--------------------------------
3   03/09/2020   
4   04/09/2020   
5   05/09/2020

排除 id 1,2 因为 table2 的 status="yes"。

我知道我的 SQL 语法是错误的。请告知正确的语法:

SELECT table1.id,table1.date
FROM table1
LEFT JOIN (select table2.id, table2.date from table2 where status!='Yes') as table2
ON table1.id=table2.id and table1.date = table2.date

【问题讨论】:

请发布您想要的结果。这对正确答案很有用 嗨 Slava,添加了想要的结果。 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。 【参考方案1】:

你需要在WHERE子句中设置正确的条件:

SELECT t1.*
FROM Table1 t1 LEFT JOIN Table2 t2
ON t2.id = t1.id AND t2.date = t1.date
WHERE COALESCE(t2.status, '') <> 'Yes'

或:

SELECT t1.*
FROM Table1 t1 LEFT JOIN Table2 t2
ON t2.id = t1.id AND t2.date = t1.date
WHERE t2.status IS NULL OR t2.status <> 'Yes'

请参阅demo。 结果:

> id | date      
> -: | :---------
>  3 | 03/09/2020
>  4 | 04/09/2020
>  5 | 05/09/2020

【讨论】:

非常感谢。我得到了我想要的结果。我想了解更多关于 WHERE COALESCE(t2.status, '') 'Yes' 的信息。它是如何运作的? COALESCE() 返回其参数的第一个非 null 或 null 如果它们都为 null。所以在这种情况下,如果它不为 null 或 ''(一个空字符串),它会返回 t2.status。【参考方案2】:

你可以使用NOT EXISTS这样的条件来解决这个问题:

SELECT Table1.*
FROM Table1
WHERE NOT EXISTS (
    SELECT id FROM Table2 WHERE Table2.id = Table1.id AND Table2.status = 'Yes'
);

【讨论】:

【参考方案3】:

如果你想过滤记录,那么使用内连接,而不是外连接:

SELECT t1.id, t1.date
FROM table1 t1 JOIN
     table2 t2
     ON t1.id = t2.id and t1.date = t2.date
WHERE t2.status <> 'Yes';

编辑:

根据您的评论,我认为NOT EXISTS 是最好的方法:

select t1.*
from table1 t1
where not exists (select 1
                  from table2 t2
                  where t1.id = t2.id and t1.date = t2.date and
                        t2.status = 'Yes'
                 );

【讨论】:

谢谢戈登。我尝试了这种语法,但不幸的是没有成功。它只给出记录号。来自 table2 的 3,但我想要记录:来自 table1 的 3、4、5。我已在我的帖子中添加了所需的结果,请查看。 @awan 。 . .样本数据有很大帮助。我想你只是想要not exists【参考方案4】:

另一种查询如下(因为我真的不明白为什么还需要加入 id):

SELECT `t1`.`id`,`t1`.`date` FROM `Table1` `t1` 
LEFT JOIN `Table2` `t2` ON `t1`.`date`=`t2`.`date`
WHERE `t2`.`status` <> 'Yes' OR `t2`.`date` IS NULL;

这是一个相关的SQLFiddle

【讨论】:

【参考方案5】:

我会这样写解决方案:

SELECT Table1.id, Table1.date
FROM Table1 LEFT OUTER JOIN Table2
  ON Table1.id = Table2.id AND Table2.status = 'Yes'
WHERE Table2.id IS NULL

如您所知,如果没有匹配,左外连接会为右表的行返回 NULL。如果匹配条件包含status='Yes',则具有其他状态值的行不匹配。

然后 WHERE 子句将结果限制为 Table1 中没有匹配的行。

【讨论】:

【参考方案6】:

试试这个

SELECT t1.* 
FROM Table1 t1 
LEFT JOIN Table2 t2 ON t2.id = t1.id 
WHERE t2.status != 'Yes' 
GROUP BY t1.id;

【讨论】:

以上是关于SQL LEFT JOIN 从第二个表中排除两条记录的主要内容,如果未能解决你的问题,请参考以下文章

MySQL LEFT JOIN 在第二个表中具有可选值

在不借助 PL/SQL 的情况下从第二个表中查找相关值

LEFT JOIN,如果存在第二个表的结果,则添加到 PHP 中的数组

sql语句中join、left join 、right join有啥区别?

Oracle Join 表与第一个表中的日期范围和第二个表中的日期

SQL语句(inner join,left out join,right out join三者的不同