Mysql 加入+;分组依据,然后筛选包含;x";而不是",;“是”;

Mysql 加入+;分组依据,然后筛选包含;x";而不是",;“是”;,mysql,Mysql,我试图通过使用内部联接从两个表中获取结果。条件是,我需要检查另一个表列必须有值“xyz”,但不能有值“abc” 表A: 身份证件 专栏1 1. 第1行 2. 第2排 在id为1的记录组中,有一个与“b.status='xyz'和b.status!='abc'”匹配的记录。因此,还将返回id 1。如果试图将B中的记录相互关联,则必须在B中进行自连接 SELECT b1.Aid FROM B b1 WHERE b1.status='xyz' AND not exists (selec

我试图通过使用内部联接从两个表中获取结果。条件是,我需要检查另一个表列必须有值“xyz”,但不能有值“abc”

表A:

身份证件 专栏1 1. 第1行 2. 第2排
在id为1的记录组中,有一个与“b.status='xyz'和b.status!='abc'”匹配的记录。因此,还将返回id 1。如果试图将B中的记录相互关联,则必须在B中进行自连接

SELECT b1.Aid FROM B b1
WHERE b1.status='xyz' 
   AND not exists 
   (select b2.id from B b2 where b2.Aid = b1.Aid and b2.status = 'abc')

ID
1
2
被正确返回,因为它们都链接到
B
中状态为
'xyz'
的记录

如果您想要排除联接表中包含任何具有“abc”的记录的结果,那么我们必须更聪明一点

在MS SQL中,我们可以使用简单的大小写表达式将过滤器转换为数字状态,这类似于数据透视:

SELECT a.id as a_id, COUNT(expr.IsABC)
FROM A as a
INNER JOIN B as b  ON b.Aid = a.id 
CROSS APPLY (SELECT IsXYZ = CASE WHEN status = 'xyz' THEN 1 END, IsABC = CASE WHEN status = 'abc' then 1 END) as expr
GROUP BY a.id
HAVING COUNT(expr.IsXYZ) > 0 AND COUNT(expr.IsABC) = 0
你真正想问的是:

A
返回ID,其中ID在
B
中至少有一个相关状态,即
'xyz'
,但在
B
中不得有任何状态为
'abc'

这也可以通过嵌套查询实现:
这在MySQL中有效-

或者您可以向我们提供一个
不存在的
样式查询:


注: 在这个人为设计的示例中,根本不需要对表
A
进行事件联接,您可以完全从表
B

SELECT Aid
FROM B
GROUP BY Aid
HAVING COUNT(CASE WHEN status = 'xyz' THEN 1 END) > 0 AND COUNT(CASE WHEN status = 'abc' then 1 END) = 0 

您必须检查每个组中的情况(
b.status='xyz'和b.status!='abc'
),而不是全局检查。您可以使用以下方法完成此操作:


是否(援助、状态)是唯一的?@草莓是enum类型,这不是我要问的:-(@草莓是的,它们是唯一的为什么不只是
b.status='xyz'
不需要额外的条件你能帮我举一个只使用连接和where条件而不是使用having和subqueries更新为MySQL版本的示例来测试@JashanPablaI想要用内部连接和where条件来完成吗唯一的。我们可以问为什么吗?唯一的另一种方法是自连接,但这实际上是与子查询相同的查询计划…我也将把其中的一种放在一起,但听起来这个故事比提供的要多得多。无论哪种方法,您都需要两个单独的比较集,所以您必须使用窗口查询、CTE或非相关子查询ry(不存在)、非相关联接(外部联接并省略匹配项)或HAVING子句。这种类型的查询是
HAVING
设计的,它明确支持通过此查询获取两个id。
SELECT a.id as a_id
FROM A as a
INNER JOIN B as b ON b.Aid = a.id 
WHERE status = 'xyz' AND NOT EXISTS (SELECT b2.id FROM B as b2 WHERE b2.AId = a.Id AND b2.status = 'abc')
GROUP BY a_id;
SELECT Aid
FROM B
GROUP BY Aid
HAVING COUNT(CASE WHEN status = 'xyz' THEN 1 END) > 0 AND COUNT(CASE WHEN status = 'abc' then 1 END) = 0 
SELECT a.id AS a_id
FROM A AS a
INNER JOIN B AS b
ON b.aid = a.id 
GROUP BY a.id
HAVING
  GROUP_CONCAT(b.status) LIKE '%xyz%' AND
  GROUP_CONCAT(b.status) NOT LIKE '%abc%'