我有一个ActivityLog表,每个网页应用中的每个网页都有一行。该表具有以下相关字段:PageTitle,UserName,ActivityDate。我想添加一个带有GridView的Usage History页面,其中包含以下列:Page Title,#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个点击(User1点击Page1,User2点击Page2,User3点击Page3),我表中的所有三行都显示3个NumUniqueUsers列,即使他们应该显示1.
有什么建议吗?
谢谢, 克里斯
编辑 - 添加生成的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
答案 0 :(得分:1)
“3个用户,每个页面分别有1个点击”
我将其解释为您的日志的含义:
在这种情况下,每个页面确实有3个唯一用户,因此您的代码是正确的
答案 1 :(得分:0)
尝试添加此扩展方法:
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();
答案 2 :(得分:0)
很难说DISTINCT在哪里迷路了。也许LinqToSql在查询翻译中丢弃了它。查看生成的sql将确认。
如果LinqToSql正在(意外地)删除了Distinct,那么这是编写该部分查询的另一种方法。
NumUniqueUsers = pageGroup.GroupBy(x => x.UserName).Count()