2012-06-08 54 views
1
計算用戶統計

我的用戶活動日誌看起來是這樣的:與LINQ

標識,用戶名,日期

我需要計算每日總條目數,當日最活躍的用戶爲最近10天。

//pseudo code 
from entry in data.UserLogs 
group by entry.Date == each day 
select username of most active user, count(Id) 

林LINQ和SQL的新來臨可以有人幫我完成這個查詢嗎?

+1

你能澄清:是的'Date'列*日期*或*日期和時間*? –

+0

它是日期時間。 – Sam

+1

主要分組可能只是「通過entry.Date.Date」組,然後 - 真正有問題的是每天*最活躍的用戶*在同一時間*。坦率地說,我認爲我會下降到TSQL - 這不是一個微不足道的查詢。 –

回答

1

我想這是你以後的樣子。只需拖放到LINQPad看到它在行動

void Main() 
{ 
    var logs = new List<UserLog> 
     { 
      new UserLog { Id= 1, Date = new DateTime(2012,1,1), Username = "cburgdorf"}, 
      new UserLog { Id= 2, Date = new DateTime(2012,1,1), Username = "cburgdorf"}, 
      new UserLog { Id= 3, Date = new DateTime(2012,1,1), Username = "cburgdorf"}, 
      new UserLog { Id= 4, Date = new DateTime(2012,1,1), Username = "Mister Foo"}, 
      new UserLog { Id= 5, Date = new DateTime(2012,1,1), Username = "Mister Foo"}, 
      new UserLog { Id= 6, Date = new DateTime(2012,1,2), Username = "Mister Bar"}, 
      new UserLog { Id= 7, Date = new DateTime(2012,1,2), Username = "Mister Bar"}, 
      new UserLog { Id= 8, Date = new DateTime(2012,1,2), Username = "cburgdorf"}, 
      new UserLog { Id= 9, Date = new DateTime(2012,1,2), Username = "Mister Foo"}, 
      new UserLog { Id= 10, Date = new DateTime(2012,1,2), Username = "Mister Foo"}, 
      new UserLog { Id= 11, Date = new DateTime(2012,1,2), Username = "Mister Foo"}, 
      new UserLog { Id= 12, Date = new DateTime(2012,1,2), Username = "Mister Bar"} 
     }; 

    logs 
     .OrderByDescending (l => l.Date) 
     .GroupBy (log => log.Date)  
     .Select (log => log 
         .GroupBy (l => l.Username) 
         .Select (l => new 
         { 
          Count = l.Count(), 
          Value = l.FirstOrDefault(), 
         }) 
         .OrderBy (l => l.Count).Last()) 
     .Select (log => new 
     { 
      Date = log.Value.Date, 
      Count = log.Count, 
      Username = log.Value.Username 
     }) 
     .Take(10) 
     .Dump(); 

     //In LINQPad use Dump() to see the results: 
     /* 
      logs 
       .OrderByDescending (l => l.Date) 
       .GroupBy (log => log.Date)  
       .Select (log => log 
           .GroupBy (l => l.Username) 
           .Select (l => new 
           { 
            Count = l.Count(), 
            Value = l.FirstOrDefault(), 
           }) 
           .OrderBy (l => l.Count).Last()) 
       .Select (log => new 
       { 
        Date = log.Value.Date, 
        Count = log.Count, 
        Username = log.Value.Username 
       }) 
       .Take(10) 
       .Dump(); 
     */ 


} 

class UserLog 
{ 
    public int Id {get;set;} 
    public DateTime Date {get;set;} 
    public string Username {get;set;} 
} 


The result is: 

    02.01.2012 00:00:00 | 3 | Mister Foo 
    01.01.2012 00:00:00 | 3 | cburgdorf 
+0

這個問題也被標記爲[tag:sql],所以你可能不得不考慮在回答時他是否使用LINQ to SQL。你在這裏使用了LINQ to Objects,並不是所有的方法都被支持。幸運的是,我認爲你在這裏是安全的,因爲你使用的所有方法都會被支持。 –

+0

絕對如此。我不確定這是否會在使用EntityFramework或LinqToEntities時轉換爲SQL。如果是這樣,它將如何執行?很難說真的,也取決於後端。對於Oracle後端,我遇到了很多「bla bla not supported exceptions」,例如,在SQL Server上,相同的查詢翻譯得很好。有時候這是一種痛苦... – Christoph

0

這應該工作。這將選擇最近10天內的最高用戶。

var query = 
    (from userLog in data.UserLogs 
    group userLog.UserName by userLog.Date.Date into usersPerDate 
    orderby usersPerDate.Key descending 
    let topUsers = 
     from user in usersPerDate 
     group 1 by user into g 
     let count = g.Count() 
     orderby count descending 
     select new 
     { 
      UserName = g.Key, 
      Count = count, 
     } 
    select topUsers.First()).Take(10); 
+0

謝謝你的回答 – Sam