将结果分组以在多个连接后获取唯一行

时间:2011-09-20 14:08:51

标签: sql-server group-by paging

免责声明:我没有对db模式的完全控制,不判断数据结构或命名约定:)

我正在使用多个连接执行此大型查询:

SELECT TOP 30   
iss.iss_lKey as IssueId,  
iss.iss_sName as IssueName,  
con.con_lKey as ContainerId,  
con.con_sName as ContainerName,  
sto.sto_lKey as StoryId,   
sto.sto_sName as StoryName,  
sto.sto_Guid as StoryGuid,  
sto.sto_sByline as Byline,  
sto.sto_created_dWhen as StoryCreatedDate,  
sto.sto_deadline_dWhen as StoryDeadline,  
sto.sto_lType as StoryType,  
sto.sto_sct_lKey as StoryCategory,  
sto.sto_created_use_lKey as CreatedBy,  
sfv.sfv_tValue as FieldValue,  
sf.sfe_lKey as StoryFieldId,  
sf.sfe_sCaption as StoryFieldCaption,   
sre.sre_lIndex as RevisionIndex  
FROM tStory30 sto  
JOIN tContainer30 con ON sto.sto_con_lKey = con.con_lKey  
JOIN tIssue30 iss ON con.con_iss_lKey = iss.iss_lKey  
LEFT OUTER JOIN tStoryRevision30 sre ON sre.sre_sto_lKey = sto.sto_lKey  
LEFT OUTER JOIN tStoryField30 sf ON sre.sre_lKey = sf.sfe_sre_lKey  
LEFT OUTER JOIN tStoryFieldValue30 sfv ON sfv.sfv_sfe_lKey= sf.sfe_lKey  
WHERE sre.sre_lIndex = 0  
AND (sto.sto_sName LIKE '%' + @0 + '%'  
OR sfv.sfv_tValue LIKE '%' + @0 + '%')";

我需要的只是StoryId的一行,包括匹配的FieldValue,如果有的话。我目前正在对代码进行分组以生成输出,但这会阻止我分页结果。

from r in items
   group r by new { r.StoryId, r.ContainerId, r.IssueId }
   into storyGroup
   select {
       storyGroup.Key.StoryId,
       storyGroup.Key.ContainerId,
       storyGroup.Key.IssueId,
       Hits = storyGroup.ToList()
    }

有没有办法在sql中实现这种分组,这样我就可以正确地分页结果(使用ROW_NUMBER()OVER)?

另外,我知道这是不好的做法,应该使用FullText搜索。计划设置solr实例,或使用sqlserver中的fulltext选项。这是第一次尝试让smthg进行。

修改

试图口头解释我试图实现的目标:

对于上下文,我们的应用程序是杂志编辑/出版商的cms。

对于特定杂志,他们有很多问题
每个问题都有很多容器(逻辑文章组) 在每个容器中你有几个故事
故事车有0或许多修改
故事的字段按修订版存储(每个修订版许多字段)
并且字段具有字段值。

我需要检索名称或第一个修订版本的字段值中具有给定文本的故事(即revisionIndex = 0的位置)。 但我还需要检索每个故事的相关数据。 (issueId,name,containerId和name,等等......) 困难的可能是检索与搜索匹配的一个fieldvalue。我不需要所有这些,只需一个......

希望这有帮助!

编辑搜索“测试”的示例数据。我简化了列,使其更容易理解。

Row | IssueId  |  IssueName    |    ContainerId  |  StoryId    |    FieldValue  
1   |   11       IssueName A          394             868          Test Marsupilami bla bla youpi
2   |   40       IssueName B          6               631          story save test
3   |   40       IssueName B          6               666          test story
4   |   4        IssueName c          30              846          test abs
5   |   4        IssueName c          30              846          absc test
6   |   4        IssueName c          30              846          hello test

我可以在我的查询中获取sqlserver中的行号,但是在这里,正如您所见,我得到了相同故事的多次。在这种情况下,我可以简单地得到以下结果:

Row | IssueId  |  IssueName    |    ContainerId  |  StoryId    |    FieldValue  
1   |   11       IssueName A          394             868          Test Marsupilami bla bla youpi
2   |   40       IssueName B          6               631          story save test
3   |   4        IssueName c          30              846          test abs

如果一个故事会在故事名称中进行测试,那么我可以在FieldValue列中使用空值,选择哪个字段值并不重要。

1 个答案:

答案 0 :(得分:0)

这是一个题外话,但是你知道你已经将左连接转换为内连接吗?

LEFT OUTER JOIN tStoryRevision30 sre ON sre.sre_sto_lKey = sto.sto_lKey   
LEFT OUTER JOIN tStoryField30 sf ON sre.sre_lKey = sf.sfe_sre_lKey   
LEFT OUTER JOIN tStoryFieldValue30 sfv ON sfv.sfv_sfe_lKey= sf.sfe_lKey   
WHERE sre.sre_lIndex = 0

试试这个

LEFT OUTER JOIN tStoryRevision30 sre ON sre.sre_sto_lKey = sto.sto_lKey   
    AND sre.sre_lIndex = 0
LEFT OUTER JOIN tStoryField30 sf ON sre.sre_lKey = sf.sfe_sre_lKey   
LEFT OUTER JOIN tStoryFieldValue30 sfv ON sfv.sfv_sfe_lKey= sf.sfe_lKey   

(我会在评论中做到这一点,但在这里更容易看到代码更改。