属性列表包含列表id(lid)和所有者id(cid)。
hasA,hasB,hasC表是属性的描述符。 hasA持有有效代码,如:For Sale,For Rent等hasB持有状态代码如:New Price,Just Listed,Under Contract等hasC持有描述代码如:Single Family,Land,Farm,Waterfront,Mountain View,Log,etc 。
我没有预见到在hasA表中使用排除,但我确实需要在hasB和hasC表中。
在这个例子中,我将仅引用这些数字。一切都可以复制到sqlfiddle。
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()对我的结果一直很好。结果集:901,903。
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 IN()不起作用。
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 IN()的使用不起作用。
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)
如果基于视觉扣除的我想要的结果集不正确,请更正此。
答案 0 :(得分:1)
我相信你正在处理“set-within-sets”查询。我喜欢group by
和having
来解决这个问题,正是因为它非常灵活。
以下内容适用于您的上一次查询:
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
表示不是。{/ p>
SQL小提琴是here。
在您的情况下,由于值来自不同的表格,您还可以使用exists
和not exists
:
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));
使用适当的索引,这在MySQL中可能会更快。