0

私の問題のドメインは広告です。そのために、というテーブルを含むデータベースがありますADVERT。広告にはファセット(つまり、準分類学的な説明用語)を含めることができます。したがって、FACETファセットを定義するFACETTERMテーブルと、各ファセットの値を含むテーブルがあります。 ADVERTFACETTERMASSIGNMENTどのファセット用語の値がどの広告に割り当てられているかを示すリンクテーブルです。

つまり、「Make」ファセットに「Honda」、「Location」ファセットに「Sussex」という値を持つ車の広告があるかもしれません。したがって、広告がadvert{PK = 14}であり、Hondaがファセットターム{PK = 1}であり、Sussexがファセットタームである場合、と{PK = 2}の行を期待します。ADVERTFACETTERMASSIGNMENT { AdvertId, FacetTermId }: 14, 114, 2

この取り決めを考えると、サセックスでホンダのための他のすべての広告を見つけるにはどうすればよいですか?言い換えるとADVERTFACETTERMASSIGNMENT、特定の広告のそのテーブルの行と一致するが、その広告の行ではない行のセットを見つけるにはどうすればよいですか?

SQL Server 2008を使用しています。IN句を使用してみましたが、部分一致が返されます。つまり、Sussex以外のすべてのHondaと、Honda以外のSussexのすべての車などです。

要件を言い換えると、ADVERTFACETTERMASSIGNMENTそれらの行に少なくとも別の特定の広告のファセットタームIDと同じファセットタームIDが含まれているすべての行を見つける必要があります。選択したコンパレータ、広告と少なくともまったく同じファセットタームがあれば、ファセットタームが多いかどうかは関係ありません。

4

3 に答える 3

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)

ここでの手法は、任意の2つの広告間の内部結合で一致するファセットの数が、左側のオブジェクト広告のファセットの数と等しくなければならないというものです。

于 2012-06-06T15:13:21.007 に答える
0

2つの用語を検索する場合、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(*)-@targetMatch) 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(*)-@targetMatch) 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

(ところで、私はウィスコンシン州サセックスからこれを投稿しています)

于 2012-06-06T14:35:18.490 に答える
0

1つのアプローチは、advertfacettermassignmentテーブルをfacettermidでそれ自体に内部結合し、advertidでグループ化して、広告間で一致するファセットの数をカウントすることです。

次に、これを最初の広告のファセットの総数と比較できます。一致する数が同じである場合、選択したコンパレータと少なくともまったく同じファセット項があります。

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
于 2012-06-06T15:13:48.077 に答える