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

发布于 2024-12-10 22:07:51 字数 1608 浏览 0 评论 0原文

我有一个 ActivityLog 表,其中包含 Web 应用程序中每个页面上的每次点击的一行。该表具有以下相关字段:PageTitle、UserName、ActivityDate。我想添加一个带有 GridView 的使用历史记录页面,该页面具有以下列:页面标题、# Hits、# Unique Users。因此,对于应用程序中的每个页面,我们将显示点击总数以及点击该页面的唯一用户数量。

我已经尝试过以下 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()
           });

NumHits 返回预期的数字;但是,NumUniqueUsers 返回的是具有点击次数的唯一用户总数,而不是每个页面的计数。因此,如果我有 3 个用户,每个用户在自己的不同页面上有 1 次点击(用户 1 点击页面 1,用户 2 点击页面 2,用户 3 点击页面 3),我的表中的所有三行的 NumUniqueUsers 列都显示 3,即使它们应该显示1.

有什么建议吗?

谢谢, Chris

编辑 - 添加生成的 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

I have an ActivityLog table with a row for each hit on each page in a web app. The table has the following pertinent fields: 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. 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:

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; however, NumUniqueUsers is coming back with the number of unique total users that have hits, not the count for each page. 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.

Any suggestions?

Thanks,
Chris

EDIT - Adding generated 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

oО清风挽发oО 2024-12-17 22:07:51

“3 个用户,每个用户在 3 个页面上都有 1 个点击”

我将其解释为您的日志如下所示:

  • User1 - Page1
  • User1 - Page2
  • User1
  • - Page3
  • User2 - Page1
  • User2 -
  • Page2 User2 - Page3
  • User3 - Page1 User3 - Page2
  • User3 - Page3

在这种情况下,每个页面确实有 3 个唯一用户,因此您的代码是正确的

"3 users, each having 1 hit on each of 3 pages"

I interpret that as meaning your log looks like:

  • User1 - Page1
  • User1 - Page2
  • User1 - Page3
  • User2 - Page1
  • User2 - Page2
  • User2 - Page3
  • User3 - Page1
  • User3 - Page2
  • User3 - Page3

With that scenario, each page does indeed have 3 unique users so your code is correct

风吹雪碎 2024-12-17 22:07:51

很难说这种 DISTINCT 迷失在哪里。也许 LinqToSql 在查询翻译中删除了它。查看生成的sql即可确认。

如果 LinqToSql(意外地)删除了 Distinct,则可以使用另一种方法来编写查询的该部分。

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

Hard to say where that DISTINCT is getting lost. Perhaps LinqToSql is dropping it in query translation. Looking at the generated sql will confirm.

If the Distinct is getting (unexpectedly) dropped by LinqToSql, here's another way to write that part of the query.

NumUniqueUsers = pageGroup.GroupBy(x => x.UserName).Count()
忘羡 2024-12-17 22:07:51

尝试添加此扩展方法:

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;
        }
    }
}

并像这样使用它:

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

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文