简体   繁体   English

如何在linq中使用分组,不同和一起计数?

[英]How do I use grouping, distinct, and count together in linq?

I have an ActivityLog table with a row for each hit on each page in a web app. 我有一个ActivityLog表,其中有一个行针对Web应用程序中每个页面上的每个命中。 The table has the following pertinent fields: PageTitle, UserName, ActivityDate. 该表具有以下相关字段:PageTitle,UserName,ActivityDate。 I'd like to add a Usage History page with a GridView that has the following columns: Page Title, # Hits, # Unique Users. 我想添加一个带有GridView的“使用历史记录”页面,该页面具有以下列:页面标题,#命中次数,#唯一用户。 So for each page in the app, we would show the total number of hits, and the number of unique users hitting that page. 因此,对于应用程序中的每个页面,我们将显示总点击数以及访问该页面的唯一身份用户数。

I have tried the following linq, which, from what I could gather in my searches, should work: 我尝试了以下linq,从搜索中可以发现,该linq应该可以正常工作:

var ual = (from activityLog in linqMetaData.UserActivityLog
           group activityLog by activityLog.PageTitle into pageGroup
           select new PageUsageStatistics()
           {
               PageTitle = pageGroup.Key,
               NumHits = pageGroup.Count(),
               NumUniqueUsers = pageGroup.Select(x => x.UserName).Distinct().Count()
           });

The NumHits comes back with the expected number; NumHits返回预期的数目; however, NumUniqueUsers is coming back with the number of unique total users that have hits, not the count for each page. 但是,NumUniqueUsers返回的是具有匹配的唯一用户总数,而不是每个页面的计数。 So if I have 3 users, each having 1 hit on their own distinct page (User1 hits Page1, User2 hits Page2, and User3 hits Page3), all three rows in my table are showing 3 for the NumUniqueUsers column, even though they should show 1. 因此,如果我有3个用户,每个用户在各自不同的页面上都有1个命中(User1命中Page1,User2命中Page2,而User3命中Page3),则表中的所有三行都将NumUniqueUsers列显示3。 1。

Any suggestions? 有什么建议么?

Thanks, Chris 谢谢克里斯

EDIT - Adding generated SQL: 编辑-添加生成的SQL:

SELECT [LPA_L1].[PageName], 
       [LPA_L1].[NumHits], 
       [LPA_L1].[NumUniqueUsers] 
FROM 
    (SELECT [LPA_L2].[PageTitle] AS [PageName], 
            [LPA_L2].[LPAV_] AS [NumHits], 
            (SELECT COUNT(*) AS [LPAV_] 
             FROM 
                 (SELECT DISTINCT [LPA_L2].[UserPrincipleName] 
                  FROM [USIC].[dbo].[UserActivityLog]  [LPA_L2]  
                 ) [LPA_L3]) AS [NumUniqueUsers] 
     FROM 
         (SELECT [LPLA_1].[PageTitle], 
                 COUNT(*) AS [LPAV_] 
          FROM [USIC].[dbo].[UserActivityLog]  [LPLA_1]   
          GROUP BY [LPLA_1].[PageTitle]
         ) [LPA_L2]
    ) [LPA_L1] 
ORDER BY [LPA_L1].[PageName] ASC

"3 users, each having 1 hit on each of 3 pages" “ 3个用户,每个用户在3页中的每一个上都有1个匹配项”

I interpret that as meaning your log looks like: 我将其解释为意味着您的日志如下所示:

  • User1 - Page1 用户1-第1页
  • User1 - Page2 用户1-第2页
  • User1 - Page3 用户1-第3页
  • User2 - Page1 用户2-第1页
  • User2 - Page2 用户2-第2页
  • User2 - Page3 用户2-第3页
  • User3 - Page1 用户3-第1页
  • User3 - Page2 用户3-第2页
  • User3 - Page3 用户3-第3页

With that scenario, each page does indeed have 3 unique users so your code is correct 在这种情况下,每个页面确实有3个唯一用户,因此您的代码是正确的

Try adding this extension method: 尝试添加此扩展方法:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> knownKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

And use it like this: 并像这样使用它:

NumUniqueUsers = pageGroup.DistinctBy(x => x.UserName).Count();

Hard to say where that DISTINCT is getting lost. 很难说DISTINCT在哪里迷路了。 Perhaps LinqToSql is dropping it in query translation. 也许LinqToSql正在查询翻译中删除它。 Looking at the generated sql will confirm. 查看生成的sql将确认。

If the Distinct is getting (unexpectedly) dropped by LinqToSql, here's another way to write that part of the query. 如果Distinct正在(意外地)被LinqToSql丢弃,则这是写该部分查询的另一种方法。

NumUniqueUsers = pageGroup.GroupBy(x => x.UserName).Count()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM