我有两张桌子:
我需要第一张表中的“clientes.id_cliente,clientes.nombre,clientes.apellido,clientes.empresa,clientes.correo”,但删除第二张表中出现的人(合同的人)
我试过这个(以及其他许多事情):
SELECT clientes.id_cliente, clientes.nombre, clientes.apellido, clientes.empresa, clientes.correo
FROM clientes
INNER JOIN contratos_clientes
ON clientes.id_cliente != contratos_clientes.id_cliente
这就是结果:
我尝试了不同的方法,但我什么都没有。
答案 0 :(得分:1)
您需要NOT EXISTS
查询:
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);
另一种选择是NOT IN
:
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);
子查询中的IS NOT NULL
是必需的,因为如果为NOT IN
列返回NULL值,contratos_clientes.id_cliente
运算符将失败。如果该列定义为NOT NULL
,则可以删除该条件。
众所周知,MySQL在NOT IN语句中非常糟糕,因此第一个可能会表现得更好。
答案 1 :(得分:1)
从概念上讲,这是NOT EXISTS
或NOT IN
- 但可能无法很好地优化。如果@a_horse_with_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
LEFT JOIN
要求左表(此处为clientes
表)中的所有行,并在右表(ON
中加入相应的行(由contratos_clientes
定义) })如果它们存在。对于左侧的每一行,如果给定行的值不存在,则右表中该行部分的所有值都将为NULL
。在您的情况下,这些是您想要的行 - 所以只需检查右侧的值是否为NULL
。最好使用一个不能NULL
的值,例如PK字段。
顺便提一下,这种查询 - “A中与B中的行不匹配的行” - 称为反连接。
(注意:通常当你只想要JOIN的左边部分时,你需要使用SELECT DISTINCT
,这样如果左侧的给定行与右边的多行匹配,它将删除重复项。但是在这种情况下,您只需要在右侧查找NULL
行,并且左侧每行最多插入一个这样的“虚拟”行,因此您不能重复,因此不需要DISTINCT
。)