至少有一个X但没有Ys查询

Dre*_*rew 4 mysql sql join subquery

我偶尔会遇到这种模式,我没有找到一种非常令人满意的解决方法.

说我有employee桌子和review桌子.每位员工都可以进行多次审核.我想找到所有employee至少有一个"好"评论但没有"坏"评论的人.

我还没有弄清楚如何在不知道员工ID的情况下让子选项工作,我还没有想出正确的连接组合来实现这一点.

有没有办法在没有存储过程,功能或带数据服务器端的情况下执行此操作?我已经与它合作但我确信还有另一种方式.

Adr*_*iro 7

由于您尚未发布数据库结构,因此我做了一些假设和简化(关于rating列,可能是数字而不是字符字段).相应调整.

解决方案1:使用联接

select distinct e.EmployeeId, e.Name
from employee e
left join reviews r1 on e.EmployeeId = r1.EmployeeId and r1.rating = 'good'
left join reviews r2 on e.EmployeeId = r2.EmployeeId and r1.rating = 'bad'
where r1.ReviewId is not null --meaning there's at least one
and r2.ReviewId is null --meaning there's no bad review
Run Code Online (Sandbox Code Playgroud)

解决方案2:使用条件计数进行分组和过滤

select e.EmployeeId, max(e.Name) Name
from employee e
left join reviews r on e.EmployeeId = r.EmployeeId
group by e.EmployeeId
having count(case r.rating when 'good' then 1 else null end) > 0
and  count(case r.rating when 'bad' then 1 else null end) = 0
Run Code Online (Sandbox Code Playgroud)

这两种解决方案都是SQL ANSI兼容的,这意味着它们都可以使用完全支持SQL ANSI标准的任何RDBMS风格(大多数RDBMS都适用).

正如@onedaywhen指出的那样,代码在MS Access中不起作用(尚未经过测试,我相信他在该主题方面的专业知识).

但我有一个说法(这可能会让一些人感到不安):我几乎不认为MS Access是一个RDBMS.我过去曾与它合作过.一旦你继续前进(Oracle,SQL Server,Firebird,PostGreSQL,MySQL,你的名字),你永远不想回来.认真.


Gri*_*fin 5

问题 - 基于B中不存在匹配的A侧返回行 - (没有"错误"评论的员工)描述了"反半连接".有很多种方法可以完成这种查询,至少有5种我在MS Sql 2005及更高版本中发现过.

我知道这个解决方案适用于MSSQL 2000及更高版本,并且是我在MS Sql 2005和2008中尝试过的5种方法中效率最高的.我不确定它是否可以在MySQL中运行,但它应该,因为它反映了一个相当常见的集合操作.

注意,该IN子句为子查询提供了employee对外部作用域中表的访问.

SELECT EE.*
FROM   employee EE
WHERE
    EE.EmpKey IN (
      SELECT RR.EmpKey
      FROM   review RR
      WHERE  RR.EmpKey = EE.EmpKey
        AND  RR.ScoreCategory = 'good'
    ) 
  AND
    EE.EmpKey NOT IN (
      SELECT  RR.EmpKey 
      FROM    review RR
      WHERE   RR.EmpKey = EE.EmpKey
        AND   RR.ScoreCategory = 'bad'
    )
Run Code Online (Sandbox Code Playgroud)