Php 查询表A中不带';t匹配表B中的行
我有两张桌子: 我需要从第一个表中删除“clients.id_cliente,clients.nombre,clients.apellido,clients.empresa,clients.correo”,但删除第二个表中出现的人员(签约人员) 我尝试了以下方法(包括许多其他方法): 这就是结果:Php 查询表A中不带';t匹配表B中的行,php,mysql,sql,Php,Mysql,Sql,我有两张桌子: 我需要从第一个表中删除“clients.id_cliente,clients.nombre,clients.apellido,clients.empresa,clients.correo”,但删除第二个表中出现的人员(签约人员) 我尝试了以下方法(包括许多其他方法): 这就是结果: 我尝试了不同的方法,但什么也没有得到。您想要一个不存在的查询: SELECT clientes.id_cliente, clientes.nombre, clien
我尝试了不同的方法,但什么也没有得到。您想要一个不存在的
查询:
SELECT clientes.id_cliente,
clientes.nombre,
clientes.apellido,
clientes.empresa,
clientes.correo
FROM clientes
WHERE NOT EXISTS (select 1
from contratos_clientes
where clientes.id_cliente = contratos_clientes.id_cliente);
另一个选项是不在中:
SELECT clientes.id_cliente,
clientes.nombre,
clientes.apellido,
clientes.empresa,
clientes.correo
FROM clientes
WHERE clientes.id_cliente NOT IN (select contratos_clientes.id_cliente
from contratos_clientes
where contratos_clientes.id_cliente IS NOT NULL);
子查询中的不为NULL
是必要的,因为如果contratos_clientes.id_cliente
列返回NULL值,则不在
运算符将失败。如果该列定义为notnull
,则可以删除该条件
众所周知,MySQL在NOT IN语句方面非常糟糕,因此第一个语句可能会表现得更好。从概念上讲,这是一个不存在的或不存在的——但这可能不会很好地优化。如果发布了@a_horse_和\u no_名称的查询执行得不好,您还可以执行以下操作:
SELECT clientes.id_cliente, clientes.nombre, clientes.apellido,
clientes.empresa, clientes.correo
FROM clientes
LEFT JOIN contratos_clientes
ON clientes.id_cliente = contratos_clientes.id_cliente
WHERE contratos_clientes.id_cliente IS NULL
LEFT JOIN
请求左表(clients
表中的所有行),如果右表(contratos\u clients
)中存在相应的行(由上的定义)。对于左侧的每一行,如果给定行的值不存在,则该行右侧表格部分的所有值都将NULL
。在您的例子中,这些是您想要的行——因此只需检查右侧的值是否为NULL
。最好使用本身不能为NULL
的值,例如PK字段
顺便提一下,这种查询——“A中的行与B中的行不匹配”——称为反连接
(注意:通常,当您只需要连接的左侧部分时,需要使用选择DISTINCT
,以便在左侧的给定行与右侧的多行匹配时删除重复项。但是在这种情况下,您只需要查找右侧的NULL
行,最多一行这样的“伪行”行在左边每行插入一行,因此您不能有重复的行,因此不需要使用DISTINCT
)pending+1作为反连接答案,因为这可能是MySQL中最有可能执行良好的查询;但是,您在
上的中的=
看起来不是有效的MySQL,不同的
可能会导致不必要的开销,因为它看起来好像PK在查询中,优化器可能仍然会花时间去重复一个不可能有重复的集。@Michael sqlbot这两个都很好的调用,谢谢你的建议。我修复了操作符,并解释了为什么DISTINCT
是不必要的,尽管在类似的连接中有时是必要的。MySQL真的在优化not EXISTS
方面也很糟糕吗?@a_horse_与_no_name说实话,我实际上不确定。我只是检查了一下(在一个类似的数据库中,有真实的数据),他们都解释了大致相同的计划。你的有一个子查询(没有优化),而我的则像标准联接一样优化。我不知道子查询是否有与重新打开每个子查询执行(左侧每行)相关的开销。我只是在一个较小的数据集上尝试了它们,它们看起来确实大致相同。与其将标题更改为“[已解决]”,不如只接受其中一个答案。这标志着它已经解决了,再加上你和回答者的分数。好的,完美,解决了。非常感谢大家
SELECT clientes.id_cliente, clientes.nombre, clientes.apellido,
clientes.empresa, clientes.correo
FROM clientes
LEFT JOIN contratos_clientes
ON clientes.id_cliente = contratos_clientes.id_cliente
WHERE contratos_clientes.id_cliente IS NULL