SQL查找至少包含N个匹配元素的所有组

时间:2016-11-02 15:06:35

标签: sql sql-server sql-server-2008 sql-server-2008-r2 group-by

我有一个系统收集SERP(搜索引擎结果)并将它们存储在数据库中。我正在使用MS SQL 2008 R2。

对于每个给定的关键字,都有一个包含10个SERP元素的SERP结果组。

Keyword -> 
    SERP Group ->
        - SERP item
        - SERP item
        - ... (3-10)

实体

public class SerpResultsGroup
{
    public SerpResultsGroup()
    {
        SerpResults = new List<SerpResult>();
    }

    public int Id { get; set; }
    public int KeywordId { get; set; }
    public Keyword Keyword { get; set; }

    public ICollection<SerpResult> SerpResults { get; set; }
}

public class SerpResult
{
    public int Id { get; set; }
    public int Position { get; set; }
    public string Url { get; set; }

    public int SerpResultsGroupId { get; set; }
    public SerpResultsGroup SerpResultsGroup { get; set; }
}

数据库架构 pic

现在我需要组合所有SERP组(或SERP项目)并找到至少N(3)个SERP项目相同的组。

这是一张用于说明逻辑的图片。 Grouping algorithm, illustration.图片说明了相关群组的匹配方式。为简单起见,图片中只有3组,但实际上数据库中可能有N组SERP项目。

假设我有一个组/关键字(group = keyword),我想找到与给定组中的任何网址至少有3(N)个匹配的所有匹配组。这些群体之间也应该至少有3个(N)相互匹配的URL。

相同的标准,但现在我们没有一个起始组,我们希望将所有组彼此分组。

我怎么能完成这项任务?我需要使用CROSS JOIN吗?

更新

以下查询似乎返回一组ID为11的给定组的匹配组,但它不会检查返回集中的每个组是否相互匹配。

SELECT sr.SerpResultsGroupId, sr1.SerpResultsGroupId
  FROM SerpResults sr
  INNER JOIN SerpResults sr1 ON sr.Url = sr1.Url
  WHERE sr.SerpResultsGroupId != sr1.SerpResultsGroupId
  AND sr.SerpResultsGroupId = 11
  GROUP BY sr.SerpResultsGroupId, sr1.SerpResultsGroupId
  HAVING COUNT(sr1.SerpResultsGroupId) >= 3

2 个答案:

答案 0 :(得分:1)

使用Group byHaving条款

Group by SERP_Group,SERP_item
Having count(1) >= 3

答案 1 :(得分:0)

3种常见项目用例的简化解决方案。 相关组将具有相同的 rnk

select         t.*

from          (select    count (*) over (partition by   s1.SERP_item,s2.SERP_item,s3.SERP_item) as cnt
                         ,rank  ()  over (order by      s1.SERP_item,s2.SERP_item,s3.SERP_item) as rnk

                        ,s1.SERP_Group
                        ,s1.SERP_item   as SERP_item1
                        ,s2.SERP_item   as SERP_item2
                        ,s3.SERP_item   as SERP_item3

                from            SERP as s1

                        join    SERP as s2

                        on      s2.SERP_Group = s1.SERP_Group 
                            and s2.SERP_item  > s1.SERP_item

                        join    SERP as s3

                        on      s3.SERP_Group = s2.SERP_Group 
                            and s3.SERP_item  > s2.SERP_item
                ) t

where       t.cnt > 1

order by    t.rnk
;
cnt rnk SERP_Group  SERP_item1  SERP_item2  SERP_item3
--- --- ----------  ----------  ----------  ----------
2   30  139         4           17          19
2   30  744         4           17          19
4   36  372         4           31          33
4   36  375         4           31          33
4   36  391         4           31          33
4   36  408         4           31          33

n 常用项目的通用解决方案。 相关组将具有相同的 rnk

with        t (SERP_Group,SERP_item,n,SERP_items)
            as
            (
                select  SERP_Group,SERP_item,1 as n,cast (SERP_item as varchar(max))
                from    SERP

                union all

                select  s.SERP_Group,s.SERP_item,t.n+1,SERP_items + ',' + cast (s.SERP_item as varchar(max))

                from            t 
                        join    SERP s 
                        on      s.SERP_Group = t.SERP_Group
                            and s.SERP_item  > t.SERP_item
                            and t.n          < 3
            )

select      cnt
           ,rnk
           ,SERP_Group
           ,SERP_items

from       (select         t.*
                           ,rank  ()  over (order by     SERP_items)    as rnk
                           ,count (*) over (partition by SERP_items)    as cnt

            from           t

            where          t.n = 3
            ) t

where       t.cnt > 1

order by    t.rnk
;
cnt rnk SERP_Group  SERP_items 
--- --- ----------  ---------- 
2   107 139         4,17,19          
2   107 744         4,17,19          
4   113 372         4,17,19          
4   113 375         4,31,33          
4   113 391         4,31,33          
4   113 408         4,31,33