Mysql SQL包含和排除

Mysql SQL包含和排除,mysql,sql,Mysql,Sql,属性列表表具有列表id lid和所有者id cid hasA、hasB、hasC表是属性的描述符。hasA持有活动代码,如:待售、待租等。hasB持有状态代码,如:新价格、刚上市、合同项下等。hasC持有描述代码,如:单身家庭、土地、农场、海滨、山景、原木等 我不打算在hasA表中使用排除,但我确实需要在hasB和hasC表中使用排除 在这个例子中,我将只引用这些数字。所有内容都可以复制到SQLFIDLE create table listings ( lid integer, cid

属性列表表具有列表id lid和所有者id cid

hasA、hasB、hasC表是属性的描述符。hasA持有活动代码,如:待售、待租等。hasB持有状态代码,如:新价格、刚上市、合同项下等。hasC持有描述代码,如:单身家庭、土地、农场、海滨、山景、原木等

我不打算在hasA表中使用排除,但我确实需要在hasB和hasC表中使用排除

在这个例子中,我将只引用这些数字。所有内容都可以复制到SQLFIDLE

create table listings (
  lid integer, 
  cid integer 
);

create table hasA (
  lid integer,
  cid integer,
  id integer
 );

create table hasB (
  lid integer,
  cid integer,
  id integer
 );

create table hasC (
  lid integer,
  cid integer,
  id integer
 );


insert into listings values
(901,4),(902,4),(903,4),(904,4),(905,4),(906,4),(907,4),(908,5);

insert into hasA values
(901,4,333),(902,4,333),(903,4,333),(904,4,333),(905,4,333),(906,4,333),(907,4,444),(908,5,333);

insert into hasB values
(901,4,700),(901,4,707),(902,4,702),(902,4,701),(903,4,701),(904,4,708),(905,4,708);

insert into hasC values
(901,4,2000),(901,4,2001),(902,4,2000),(902,4,2003),(903,4,2000),(903,4,2001),(904,4,2015);
我需要帮助建立两个查询。这可能已经得到了回答,但我确实仔细查看了现有的解决方案,无法将其他解决方案应用于我的问题。我的SQL是基本的

在第一个查询中,我包括了hasA中有333个和hasC中有2001个的所有列表。使用IN对我的结果总是很好。结果集:901903

select a.lid 
  from listings a, hasA b, hasC c 
 where a.lid = b.lid 
   and a.lid = c.lid 
   and a.cid = b.cid 
   and a.cid = c.cid 
   and b.id in (333) 
   and c.id in (2001);
现在,我正在尝试获取hasC无法包含2001的所有列表。基于视觉推断,期望的结果集为:902、904、905、906。我在下面使用的NOT不起作用

select a.lid 
  from listings a, hasA b, hasC c 
 where a.lid = b.lid 
   and a.lid = c.lid 
   and a.cid = b.cid 
   and a.cid = c.cid 
   and b.id in (333) 
   and c.id not in (2001);
下面的示例涉及相同的逻辑,但包括hasB和hasC表

直接包含效果良好,并给出结果集:903

select a.lid 
  from listings a, hasA b, hasB c, hasC d 
 where a.lid = b.lid 
   and a.lid = c.lid 
   and a.lid = d.lid 
   and a.cid = b.cid 
   and a.cid = c.cid 
   and a.cid = d.cid 
   and b.id in (333) 
   and c.id in (701) 
   and d.id in (2001)
现在,我正在尝试获取hasC无法包含2001的所有列表。根据视觉推断,所需结果集为:902。我在下面使用的NOT不起作用

select a.lid 
  from listings a, hasA b, hasB c, hasC d 
 where a.lid = b.lid 
   and a.lid = c.lid 
   and a.lid = d.lid 
   and a.cid = b.cid 
   and a.cid = c.cid 
   and a.cid = d.cid 
   and b.id in (333) 
   and c.id in (701) 
   and d.id not in (2001)

如果基于视觉推断的期望结果集不正确,请更正此错误。

我相信您正在处理集合内查询。我喜欢分组讨论,因为它非常灵活

以下是您最后的查询:

select a.lid
from listings a left join
     hasA b
     on a.lid = b.lid left join
     hasB c
     on a.cid = c.cid left join
     hasC d
     on a.lid = d.lid
group by a.lid
having sum(b.id in (333)) > 0 and
       sum(c.id in (701)) > 0 and
       coalesce(sum(d.id in (2001)), 0) = 0;
having子句中的每个条件都对应于其中一个条件。>0表示在列表中可以找到该条件。=0表示它不是

SQL小提琴是

在您的情况下,由于值来自不同的表,您还可以使用exists和not exists:


有了适当的索引,MySQL中的查询速度可能会更快。

您是要求一个查询还是几个查询?很难说你在追求什么。你提到期望的结果在某一点上是902和903,然后你说903是好的,然后期望的结果是904。你能解释一下期望的结果是什么,为什么吗?我想问两个问题。通过直观地查看表内容,我再次检查了所需的结果集,现在感觉它们是正确的。第一个查询返回902和903。如果为hasc表d添加别名,则第二个查询返回902、904、905、906。@BrianDeMilia。观察力很好。不仅需要左连接,因为某些表缺少相应的ID,而且当没有匹配项且总和为NULL而不是0时,可能会出现=0的情况。这两个查询都给出了902904905906,但我觉得正确的结果集应该是902。列出cid=4的条件在hasA中必须有333条记录,hasB中必须有701,hasC中不能有2001。清理后的版本现在给出的预期结果集是:902从列表A中选择A.*存在的从hasA b中选择1,其中A.lid=b.lid和b.cid=4,b.id在333中,存在的从hasB c中选择1,其中A.lid=c.lid和c.cid=4,c.id在701中,不存在的从中选择1其中a.lid=d.lid和d.cid=4和d.id在2001年;
select a.*
from listings a
where exists (select 1 from hasA b where a.lid = b.lid and b.id in (333)) and
      exists (select 1 from hasB c where a.cid = c.cid and c.id in (701)) and
      not exists (select 1 from hasC d where a.lid = d.lid and d.id in (2001));