合并同一表的查询N次

时间:2017-02-11 20:34:30

标签: c# sql linq group-by

我有一个单词表,一个查找表,其中显示了在文档中找到这些单词的位置,以及该单词在该文档中出现的次数。因此,可能有一条记录表明Alpha在文档X中存在5次,而Beta在文档X中存在3次,而另一种在文档Y中存在两次Beta。

用户可以输入多个单词进行搜索,因此“快速棕色狐狸”是三个查询,但“快速棕色狐狸跳跃”是四个查询。虽然我可以依次得到每个单词的得分结果集,但我真正想要的是为每个单词添加出现次数,这样最高的结果就是所有单词的最高出现次数。

文档可能有数百个“快速”和“棕色”事件,但没有“狐狸”出现。结果应该仍然包括在内,因为它的分数可能高于只有“快速”,“棕色”和“狐狸”各一个的文档。

我无法解决的问题是如何将1到N个查询与出现的总和合并。我认为我需要使用GROUP BY和SUM()但不确定。 Linq首选但SQL可以。 MS SQL 2016。

我想将结果传递给页面索引器,因此结果上的for-each不起作用,而且我们正在讨论80,000个单词记录,300万个文档单词记录和100,000个文档记录。

// TextIndexDocument:
// Id | WordId | Occurences | DocumentId | (more)
//
// TextIndexWord:
// Id | Word

foreach (string word in words)
{
    string lword = word.ToLowerInvariant();
    var results = from docTable in db.TextIndexDocuments
                  join wordTable in db.TextIndexWords on docTable.WordId equals wordTable.Id
                  where wordTable.Word == lword
                  orderby docTable.Occurences descending
                  select docTable;
    // (incomplete)
}

更多信息

我知道建议使用全文搜索。那么问题是如何将来自六个不相关的表(在论坛帖子,文章,产品......中搜索)的结果排序到一个统一的结果集中 - 让我们说记录ID,记录类型(文章/产品/论坛),以及得分了。最好的结果可能是一个论坛帖子,而下一个最好的点击是几篇文章,然后是产品,然后是另一个论坛帖子等等。 TextIndexDocument表已在所有相关表中包含此信息。

3 个答案:

答案 0 :(得分:1)

据我所知,这不能,或者至少很容易在LINQ中完成,特别是以任何一种高效的方式。

假设您的DBA允许,您应该考虑的是Full-Text索引存储在SQL Server中的文档。根据我的理解,RANK运算符正是您正在寻找的,已针对全文进行了高度优化。

回应你的评论:(抱歉没有注意到)

您需要执行一系列子查询或Common-Table-Expressions。 CTE一开始有点难以习惯写作,但是一旦习惯了它们,它们就比用子查询编写的相应查询要优雅得多。无论哪种方式,查询执行计划都将完全相同,因此从CTE路线获得的性能不会提高。

答案 1 :(得分:1)

假设您可以在TextIndexDocuments中创建导航属性Document

public virtual ICollection<TextIndexDocuments> TextIndexDocuments{ get; set; }

以及TextIndexDocument中的导航属性:

public virtual TextIndexWord TextIndexWord { get; set; }

(强烈推荐)

然后您可以使用属性来获得所需的结果:

var results = 
    (
        from doc in db.Documents
        select new
        {
            doc,
            TotalOccurrences = 
                   doc.TextIndexDocuments
                      .Where(tid => lwords.Contains(tid.TextIndexWord.Word))
                      .Sum(doc => doc.Occurrences)
        }
    ).OrderByDescending(x => x.TotalOccurrences)

答案 2 :(得分:0)

您想要为每个文档的单词添加出现次数。因此,按文档ID分组,使用SUM并按总降序排序:

select documentid, sum(occurences)
from doctable
where wordid in (select id from wordtable where word in 'quick', 'brown', 'fox') 
group by documentid
order by sum(occurences) desc;