2

我有这个加入表:

 CREATE TABLE [TagMap](
[intItemId] [bigint] NOT NULL,
[intTagId] [bigint] NOT NULL,
 CONSTRAINT [PK_TagMap_intItemId] PRIMARY KEY CLUSTERED 
 (
[intItemId] ASC,
[intTagId] ASC
 ))

我的 sproc 发现与 seedItemId 关联的标签,然后选择与这些标签关联的其他 intItemId,如下所示:

 declare @baseTags table    (intTagId bigint primary key clustered);

INSERT INTO @baseTags (intTagId)
SELECT TOP 20 t1.intTagId
FROM   TagMap t1
WHERE t1.intItemId = 776

 SELECT TOP 500 t1.intItemId
 FROM   TagMap t1
      JOIN @baseTags t2
       ON t1.intTagId = t2.intTagId
 GROUP  BY t1.intItemId
 ORDER  BY Count(*) DESC

我需要做的是在两个 intItemIds 之间指定一个最小标签关联数 - 比如 10 - 低于该值不返回值。也就是说在TagMap 表中可以找到十个或更多的两个intItemIds 共有的intTagIds,这很好,我们选择它——否则忽略它。

因此,例如给定以下数据:

 CREATE TABLE #TagMap(
 [intItemId] [bigint] NOT NULL,
 [intTagId] [bigint] NOT NULL,
 CONSTRAINT [PK_TagMap_intItemId] PRIMARY KEY CLUSTERED 
 (
 [intItemId] ASC,
 [intTagId] ASC
 ))

 insert into #TagMap
 (intItemId, intTagId)
 values 
 (1, 100),(1, 200),(1, 300),
 (2, 100),(2, 200),         (2, 500),(2, 600),
 (3, 100),                  (3, 500),(3, 600)

假设匹配阈值为二。

如果种子是 intItemId 1,则只应返回 intItemId 2(它有两个匹配的标签 Id:100 和 200,而 intItemId 3 有一个:100,低于阈值)。

如果种子是 intItemId 2,则应返回 intItemId 1 和 3(intItemId 1 匹配标签 ID 100 和 200,而 intItemId 3 匹配标签 ID 500 和 600)。

如果种子是 intItemId 3,则只应返回 intItemId 2(它有两个匹配的标签 ID:500 和 600,而 intItemId 有一个:100,低于阈值)。

请问有什么办法吗?

干杯,马特

4

2 回答 2

2
SELECT
  [foreign].intItemID
FROM
  #TagMap    AS [primary]
INNER JOIN
  #TagMap    AS [foreign]
    ON [foreign].intTagID = [primary].intTagID
WHERE
  [primary].intItemID = 1
GROUP BY
  [foreign].intItemID
HAVING
  COUNT(distinct [foreign].intTagID) >= @threshold

但是请注意,这非常糟糕。因为JOIN搜索“具有这些标签中的任何一个”,然后只有在HAVING子句中才能指定“具有所有这些标签”。

根据我的经验,您可以进行一些小的优化,但我发现最有价值的方法是将结果缓存到更标准的映射表中。必要时更新它们。(标签数据的内容很少改变。)

于 2012-04-13T13:31:04.637 回答
1

这似乎可以做到(@InterestItem从 1、2、3 不等,它似乎产生了您要求的结果):

declare @InterestItem int
set @InterestItem = 1
declare @Threshold int
set @Threshold = 2

select
    tm2.intItemId,
    COUNT(*)
from
    #TagMap tm1
        inner join
    #TagMap tm2
        on
            tm1.intTagId = tm2.intTagId and
            tm2.intItemId <> tm1.intItemId
where
    tm1.intItemId = @InterestItem
group by
    tm2.intItemId
having
    COUNT(*) >= @Threshold

我目前将 包括COUNT在结果集中,但这并不是完成这项工作所必需的。

于 2012-04-13T13:37:33.977 回答