2012-04-13 3 views
2
에 포인트를 가입

I이 결합 테이블이 있습니다로 명시 최소 수는 SQL

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

내 SPROC는 seedItemId과 관련된 태그를 발견하고 다음과 같이 해당 태그와 관련된 다른 intItemIds 선택을 : 내가 태그 협회의 최소 수를 지정되는 필요 무엇

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 

는 - 10 말 - 값이 반환되지 않는 아래 두 intItemIds 사이. 즉, TagMap 테이블에는 두 개의 intItemIds가 공통으로 가지고있는 10 개 이상의 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).

아이디어가 있습니까?

환호, 매트이 꽤 심하게 확장 것을 그러나

답변

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 절에 지정할 수 있기 때문에 "이러한 태그의 모든있다".

제 경험으로는 사소한 최적화 작업을 수행 할 수 있지만 가장 보람있는 방법은 결과를 표준 매핑 테이블에 캐시하는 것입니다. 필요한 경우 업데이트하십시오. (. 태그의 내용은 데이터가 매우 자주 변경)

+0

성능에 대한 경고를 보내 주셔서 감사합니다. 실제 데이터에서이 값을 사용할 때 나를 물어 뜯을 수 있습니다. –

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이 포함되어 있지만이 작업을 수행 할 필요는 없습니다.

관련 문제