2011-12-30 31 views
4

关系(我有甚解释这个问题很难)SQL,比较安置在多个链接表

我有5个表,A,​​,ZBZB

​​表示AZ之间的多对多关系。 BZ表示BZ之间的多对多关系。

我想的结果集是A B其中B被链接到一个给定A的全套Z

所以,让我们说,Z是一个标签表,包含:

Tag1 
Tag2 
Tag3 

A是一个对象表,包含:

ObjectA 
ObjectB 
ObjectC 

B是一个小部件表,包含:

WidgetX 
WidgetY 
WidgetZ 

​​co ntains:

ObjectA Tag1 
ObjectA Tag2 
ObjectB Tag3 
ObjectC Tag2 
ObjectC Tag3 

BZ包含:

WidgetX Tag1 
WidgetX Tag2 
WidgetY Tag2 
WidgetY Tag3 
WidgetZ Tag3 

我希望我的结果设置为:

ObjectA WidgetX 
ObjectB WidgetY 
ObjectB WidgetZ 
ObjectC WidgetY 

这是可行的查询,或者我应该拉回来一些中间套数据并在代码中迭代?

回答

3

好的,主要的编辑根据您的反馈来调整它。这是一个有点缺憾,但在这里你去:

select distinct 
    x.aid, 
    x.bid 
from 
    (select 
     az.aid, 
     bz.bid, 
     (select COUNT(1) from az az1 where az1.aid = az.aid) as acount, 
     (select COUNT(1) from bz bz1 where bz1.zid in (select zid from az az1 where az1.aid = az.aid) and bz1.bid = bz.bid) as bcount 
    from 
     az 
     inner join bz on 
      az.zid = bz.zid 
    ) x 
where 
    x.acount = x.bcount 

它使用子查询讨厌得到正确的计数,然后限制根据您的标准我们的行集。

+0

这不是正确的结果集。 ObjectA链接到Tag1和Tag2。 WidgetY未链接到Tag1,因此ObjectA到WidgetY无效。 – 2011-12-30 19:52:51

+0

@JacobG - 尽量在将来使用更好的表名和实际数据,相信它或不是这些例子使得帮助更加困难。 – JonH 2011-12-30 19:54:41

+0

@JacobG - 好吧,修正是正确的...让我知道,如果这对你有用。 – Eric 2011-12-30 20:58:57

3

主要编辑:

随着舍甫琴科正确地指出,我有坚持错误的结束我先走了。这应该会做得更好:

select a, b.b 
from az cross join b 
left outer join bz on az.z = bz.z and b.b = bz.b 
group by a, b.b 
having sum(case when bz.b is null then 1 else 0 end) = 0 

交叉连接建立了一个表,它表示每个b都满足AZ中每个a的条件的假设。左外连接检查这个假设,并在该假设失败的bz.b列中留下空值。有条款排除那些包含一个或多个这种空值的a-b配对。

+0

从我如何理解问题出发,对象的标记集应该是小部件的子集,以便对象与小部件相匹配。您的查询将返回太多匹配。 – 2011-12-30 20:58:35

+1

+1,我正在考虑这件事情,然后放弃嗜睡。只有我在考虑交叉连接到'(从bz选择不同的b)'而不是'b',但是这不会影响结果,并且可能效率较低。 – 2011-12-31 14:03:18

+0

+1这个也适用。尽管这比Eric的解决方案慢了几个数量级。我玩的好策略。谢谢! – 2012-01-03 15:51:11