2012-06-06 60 views
0

我的问题域是广告,为此,我有一个数据库,其中包含一个名为ADVERT的表。广告可以具有方面(即,准分类描述术语)。所以,有一个FACET表定义了构面和一个FACETTERM表,其中包含每个构面的值。 ADVERTFACETTERMASSIGNMENT是链接表,它说明哪些方面术语值被分配给哪个广告。查找链接表中的相关行

因此,您可能有一辆汽车的广告,因为它的“制造”方面具有“本田”的价值,“萨塞克斯”的“位置”方面有广告。所以如果广告是{PK = 14},本田是方面{PK = 1}和苏塞克斯是方面{PK = 2},你期望行ADVERTFACETTERMASSIGNMENT { AdvertId, FacetTermId }: 14, 114, 2

鉴于此安排,我该如何着手寻找所有其他广告是哪里为Hondas在苏塞克斯?换句话说,我如何在ADVERTFACETTERMASSIGNMENT中找到一组行,该行匹配给定广告的表中的行,但哪些不是来自该广告?

我使用SQL Server 2008中我一直在使用IN子句试过,但是这将返回部分匹配,即除了在苏塞克斯的所有本田和苏塞克斯所有的汽车不属于本田等

要重申我的要求,我需要找到ADVERTFACETTERMASSIGNMENT中的所有行,其中这些行至少包含与另一个给定广告相同的facet-term id。不管它是否有更多的方面术语,只要它至少与所选择的比较器广告具有完全相同的方面术语。

+2

请显示架构,示例数据和所需结果。我感觉我回到了高中,试图破译我最不喜欢的老师的一个神秘字。 –

回答

2

这基本上是一个EAV - 实体,属性,具有固定选择值的值模型。

WITH FLATTENED AS (
    SELECT a.ADVERT_ID, ft.FACETTERM_ID 
    FROM ADVERT a 
    INNER JOIN ADVERTFACETTERMASSIGNMENT afta 
     ON afto.ADVERT_ID = a.ADVERT_ID 
    INNER JOIN FACETTERM ft 
     ON ft.FACETTERM_ID = afta.FACETTERM_ID 
    INNER JOIN FACET f 
     ON f.FACET_ID = ft.FACET_ID 
) 
SELECT rhs.ADVERT_ID, COUNT(*) 
FROM FLATTENED lhs 
INNER JOIN FLATTENED rhs 
    ON lhs.ADVERT_ID = @SOME_ID 
    AND rhs.ADVERT_ID <> lhs.ADVERT_ID 
    AND rhs.FACETTERM_ID = lhs.FACETTERM_ID 
GROUP BY rhs.ADVERT_ID 
HAVING COUNT(*) = (SELECT COUNT(*) FROM FLATTENED WHERE ADVERT_ID = @SOME_ID) 

的这里的技术是,在所述内匹配面的数量的任何两个之间广告加入具有等于在左手侧上的对象的广告小平面的数量。

+0

对于通用解决方案而言,但使用FLATTENED而不是使用ADVERTFACETTERMASSIGNMENT(AFTA)有什么意义? 是不是FLATTENED只是AFTA的验证副本与额外的开销必须加入表? –

+0

@ Mr.Mindor没有真正的理由,我只是加入了一切,所以我不必重复它,如果我需要它(因为这是一套自我加入)。我认为在现实生活中,这样的观点已经存在(在EAV系统中)。 –

+0

非常感谢你。这显然有效(我已经在我的数据库中进行了测试并获得了正确的结果),但作为一个非SQL开发人员,我不明白为什么它有效。你能把它拼出来吗? –

0

好地方ADVERTFACETTERMASSIGNMENT是{AdvertId,FacetTermId} 的两届任期搜索...

select fta1.AdvertID 
from ADVERTFACETTERMASSIGNMENT fta1 
join ADVERTFACETTERMASSIGNMENT fta2 on fta1.AdvertID = fta2.AdvertID 
where fta1.FacetTermId = @searchFacet1 and fta2.FacetTermID = @searchFacet2 
and fta1.AdvertID <> @searchAdvertId 

与工作示例一般的答案:

declare @AdvertFacetTermAssignment table (AdvertId int, FacetTermId int) 

insert into @AdvertFacetTermAssignment values 
(1,10), (1,11), (2,10), (3,11), (4,10), (4,11), (5,10), (5,11), (5,12), (6,10), (6,12), (6,13), (7, 10), (7, 11), (8, 12), (9,10), (9,11), (9,12), (10, 10), (10,12) 

declare @searchAdvertId int = 1 
declare @targetMatch int = (select COUNT(*) from @AdvertFacetTermAssignment where AdvertId = @searchAdvertId) 

select aft2.AdvertId from @AdvertFacetTermAssignment aft1 
join @AdvertFacetTermAssignment aft2 
on aft1.FacetTermId = aft2.FacetTermId and aft1.AdvertId <> aft2.AdvertId 
where aft1.AdvertId = @searchAdvertId 
group by aft2.AdvertId 
having COUNT(*) = @targetMatch 

结果= 4,5,7 ,9

最后一个不是要求的内容,而是抓取类似的一切(一些匹配的方面)和订单的相似程度。
(所有比赛都一视同仁)

select aft2.AdvertId, COUNT(aft1.AdvertId) as matches, ABS(COUNT(*)[email protected]) as nonMatches 
from @AdvertFacetTermAssignment aft1 
right outer join @AdvertFacetTermAssignment aft2 
on aft2.FacetTermId = aft1.FacetTermId 
    and aft1.AdvertId = @searchAdvertId 
    and aft2.AdvertId <> @searchAdvertId 
group by aft2.AdvertId 
having COUNT(aft1.AdvertId) > 0 
order by COUNT(aft1.AdvertId) DESC, ABS(COUNT(*)[email protected]) ASC 

结果:

AdvertId matches nonMatches 
4  2  0 
7  2  0 
9  2  1 
5  2  1 
10  1  0 
6  1  1 
2  1  1 
3  1  1 

(顺便说一句,我从苏塞克斯,威斯康星张贴本)

0

一种方法可以是在facettermid, 和group by advertid之间内部加入advertfacettermassignment表,以计算广告之间的匹配构面的数量。

然后,您可以将其与第一个广告中的构面总数进行比较,如果匹配数 相同,则它至少与所选比较器具有完全相同的构面条件。

在SQL SERVER 2008中,您可以使用CTE使其更容易一些。像这样:

;WITH m AS 
    (SELECT advertid,candidateid,COUNT(*) as matchingfacets FROM (
     SELECT a.advertid,b.advertid as candidateid FROM advertfacettermassignment a 
     INNER JOIN advertfacettermassignment b ON a.facettermid=b.facettermid) sub 
    GROUP BY advertid,candidateid) 
,t AS 
    (SELECT advertid,COUNT(*) as TotalFacets FROM advertfacettermassignment GROUP BY advertid) 
SELECT 
    totalfacets.advertid, 
    matchingfacets.candidateid, 
    t.totalfacets, 
    m.matchingFacets 
FROM m INNER JOIN t 
ON m.advertid=t.advertid 
WHERE matchingfacets=totalfacets