Php 查询表A中不带';t匹配表B中的行

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

我有两张桌子:

我需要从第一个表中删除“clients.id_cliente,clients.nombre,clients.apellido,clients.empresa,clients.correo”,但删除第二个表中出现的人员(签约人员)

我尝试了以下方法(包括许多其他方法):

这就是结果:


我尝试了不同的方法,但什么也没有得到。

您想要一个不存在的
查询:

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