簡體   English   中英

用多列分組

[英]Group By with multiple column

我在下表中有數據

 RowId | User | Date -------------------------- 1 A 2015-11-11 08:50:48.243 2 A 2015-11-11 08:51:01.433 3 B 2015-11-11 08:51:05.210 

嘗試獲取數據如下:

 User, Date, Count A 2015-11-11 2 B 2015-11-11 1 Select User,Date,Count(User) from Table1 Group By User,Date 

由於涉及“日期”字段中的時間,它返回了3行。 如何在SQL和Linq中獲得它。 請給我建議。

編輯:

我能夠在SQL中獲得它

  Select User,Cast(Date as Date),Count(User) from Table1 Group By User,Cast(Date as Date) 

編輯:

添加linq查詢

 var details = db.table1.GroupBy( r => new { r.RowId,r.User,r.Date}) .Select(g => new {Name = g.Key, Count = g.Count()}).ToList(); 

如果時間有問題,可以先將其轉換為:

select User, CAST(dateColumn AS DATE) as dateConverted
into #tempTable
from myTable

然后使用窗口函數或分組依據:

select *,
    count(user) over (partition by date) as userCount
    from #tempTable

這應該可以在SQL Server中使用,不了解Linq

編輯:如果日期部分是問題,只需從表中select into帶有強制轉換日期的表即可。 這樣,Linq中就不會出現此問題。

var grouped = from d in db.MyTable.AsEnumerable()
              group d by new {
      User = d.User, 
      Date=d.Date.HasValue ? d.Date.Value.Date : (DateTime?)null} into g
              select new {User=g.Key.User, Date=g.Key.Date, Count=g.Count()};

遲早有人會說這不是服務器端分組,並且會受到性能的影響,這是正確的。 如果沒有Enumerable,它將在服務器端,但以每個組的另一個調用為代價,因此這是另一種方式:

public class MyResult
{
  public string User {get;set;}
  public DateTime? Date {get;set;}
  public int Count {get;set;}
}

var grouped = db.ExecuteQuery<MyResult>(@"select [User], 
  Cast([Date] as Date) as [Date],
  Count(*) as [Count]
from myTable
group by [user], Cast([Date] as Date)");

編輯:我不知道為什么我以前想過另一種方式,這只會在服務器端工作並做到,不需要AsEnumerable():

var grouped = from d in db.MyTable
              group d by new {
      User = d.User, 
      Date=d.Date.HasValue ? d.Date.Value.Date : (DateTime?)null} into g
  select new {User=g.Key.User, Date=g.Key.Date, Count=g.Count()};

對於Linq Query,只需執行以下操作:(您需要使用System.Data.Entity.SqlServer命名空間進行導入。

執行此linq查詢,所有計算都在服務器數據庫上完成。 請注意, Table1s代表Table1DbSet ,而context是您的DbContext實例。

var query = from item in context.Table1s
    group item by new
    {
       item.User, 
       Year = SqlFunctions.DatePart("yyyy", item.Date), 
       Month = SqlFunctions.DatePart("mm", item.Date), 
       Day = SqlFunctions.DatePart("dd", item.Date)
    } into g
    select new { g.Key.User, g.Key.Year, g.Key.Month, g.Key.Day, Count = g.Count() };

然后像這樣創建最終結果:

var result = query.ToList().Select(p =>
    new
    {
        p.User,
        Date = new DateTime(p.Year.Value, p.Month.Value, p.Day.Value),
        p.Count
    }).ToList();

其他解決方案是創建一個SQL視圖,DbContext將使用該SQL視圖來檢索所需的數據。 SQL View主體必須是您在問題中編寫的SQL。

編輯2:DbFunctions

就像Cetin Basoz在評論中指出的那樣,我們也可以使用System.Data.Entity.DbFunctions 而且代碼比使用SqlFunctions簡潔 這僅適用於EF 6及更高版本。 使用SqlFunctions的版本可用於EF 4及更高版本。

var query = from item in context.Table1s
    group item by new
    {
        item.User, 
        Date = DbFunctions.TruncateTime(item.Date)
    } into g
    select new { g.Key.User, g.Key.Date, Count = g.Count() };

編輯1:這是Cetin Basoz的回答所特有的:

眾所周知,使用AsEnumerable不能高效地完成所需的工作。 他給我們的第二個解決方案是:

var grouped = from d in db.MyTable
          group d by new {
  User = d.User, 
  Date=d.Date.HasValue ? d.Date.Value.Date : (DateTime?)null} into g
  select new {User=g.Key.User, Date=g.Key.Date, Count=g.Count()};

由於以下原因,此解決方案不起作用:

LINQ to Entities不支持指定的類型成員'Date'。 僅支持初始化程序,實體成員和實體導航屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM