2012-02-20 82 views
1

我試圖使Linq到SQL查詢返回日期分組結果。挑戰在於每天/每週/每月/每季度根據可枚舉參數(週期性)進行分組。下面,我目前的LINQ to SQL查詢:Linq到SQL組按日期取決於參數(每日,每月....)

var TotalGroupedInvoices = from c in entidades.InvoicesView 
        group c by (periodo == periodicity.Daily) ? c.InvoiceDate.Date : 
             period == periodicity.Weekly?  c.InvoiceDate.Date.AddDays(-(double)c.InvoiceDate.DayOfWeek) : 
             period == periodicity.Monthly? new DateTime(c.InvoiceDate.Year,c.InvoiceDate.Month ,1) : 
             period == periodicity.Quarterly? new DateTime(c.InvoiceDate.Year, c.InvoiceDate.Month - (c.InvoiceDate.Month % 3) +1, 1) : 
             period == periodicity.Anual ? new DateTime(c.InvoiceDate.Year, 1, 1) : inicio into Periods 
        select new 
        { 

         period = Periods.Key, 
         Total = Periodos.Sum(c => c.Total) 
        }; 

對於澄清,看一看的季度期間的代碼片段:

period == periodicity.Quarterly? new DateTime(c.InvoiceDate.Year, c.InvoiceDate.Month - (c.InvoiceDate.Month % 3) +1, 1) 

因此,日期,第一季度,如:月/二千零十二分之十二,2012年1月/ 15/2012年3月/ 20/2012年,我將所有人分組在2012年1月1日開始的季節,因此它按預期工作。

首先我想知道查詢效率。你怎麼看待這件事?也許最好是整數翻譯SQL Server效率的時期,並重新翻譯到客戶端的日期,但我不確定這一點。

在另一方面,每週工作組每週分組日期,每週的第一個星期日:

period == periodicity.Weekly? c.InvoiceDate.Date.AddDays(-(double)c.InvoiceDate.DayOfWeek) 

...那是不正確的我,因爲我是從西班牙派來的,周的星期一開始。我怎樣才能修正周組以考慮到這一點?

所以,總結:

  • 這個怎麼樣的LINQ to SQL查詢效率?
  • 我怎樣才能每週按此分組,但考慮從星期一到星期日的幾周?

非常感謝! PD:對不起我的英語水平。

回答

0

要回答第二部分,你只需要做一些「日」算術。爲此,您可以在線或者作爲一個單獨的功能(例如,擴展方法):

public static DateTime FirstDayOfWeek (this DateTime date) 
{ 
    double offset = (date.DayOfWeek == DayOfWeek.Sunday) ? -6 : (DayOfWeek.Monday - date.DayOfWeek); 
    return date.AddDays(offset); 
} 

然後在您的LINQ:

period == periodicity.Weekly ? c.InvoiceDate.FirstDayOfWeek 

然而,鑑於你是從SQL檢索這一點,你可能只是想看看那裏的日期函數,例如DATEPART並在你的查詢中返回它們

+0

非常感謝,我試了幾個小時內,這個解決方案和售後的任何疑慮或設置爲接受的答案。 – 2012-02-20 13:17:40

+0

太棒了!注意我沒有聲稱回答你的問題的第一部分 - 我會嘗試用不同的方法來觀察性能。爲了可讀性,我認爲有一個單獨的函數來計算代表期限日期 – kaj 2012-02-20 13:28:31

+0

因爲我正在編寫Linq-to-SQL,所以你的方法有問題:方法'System.DateTime FirstDayOfWeek(System.DateTime)'doesn不支持SQL轉換。那麼,是否有可能進行另一項工作報告?謝謝 – 2012-02-20 16:04:20

2

要回答第一部分,你並不是真的想將枚舉值傳遞到數據庫,並讓它決定使用哪個代碼分支。你有所有的信息在本地做出決定。

Expression<Func<InvoicesView, DateTime>> groupingExpr = c => c.InvoiceDate.Date; 

if (period == periodicity.Weekly) 
{ 
    groupingExpr = c => c.InvoiceDate.Date.AddDays(-(double)c.InvoiceDate.DayOfWeek); 
} 
else if (period == periodicity.Monthly) 
{ 
    groupingExpr = c => new DateTime(c.InvoiceDate.Year,c.InvoiceDate.Month ,1); 
} 
else if (period == periodicity.Quarterly) 
{ 
    groupingExpr = c => new DateTime(c.InvoiceDate.Year, c.InvoiceDate.Month - (c.InvoiceDate.Month % 3) +1, 1); 
} 
else if (period == periodicity.Anual 
{ 
    groupingExpr = c => new DateTime(c.InvoiceDate.Year, 1, 1); 
} 


var TotalGroupedInvoices = entidades.InvoicesView 
    .GroupBy(groupingExpr) 
    .Select(grouped => new { 
    period = grouped.Key, 
    Total = grouped.Sum(c => c.Total) 
    }); 

這裏是最好的,我可以做與查詢理解語法交融groupingExpr:

var TotalGroupedInvoices = from grouped in entidades.InvoicesView.GroupBy(groupingExpr) 
    select new { 
    period = grouped.Key, 
    Total = grouped.Sum(c => c.Total) 
    }; 
+0

謝謝,我是Linq-to-SQL的新手,並沒有注意到我的代碼和你的代碼之間的區別,我會用LinqPad工具嘗試你的代碼並研究它們之間的差異。我會在幾個小時內回覆併發布任何疑問或設置爲已接受的答案。謝謝! – 2012-02-20 15:07:48

+0

@FranCD我會改變代碼,使差異更清晰。您可能想要在調試器中檢查groupingExpr。 – 2012-02-20 15:20:03

+0

嗨大衛,新的代碼非常清晰,正如你所說,生成的SQL隨着你的方法而縮短。我想知道是否可以使用groupingExpression作爲用理解語法(作爲菜鳥,這個語法似乎是最清晰的)編寫的Linq查詢的一部分。謝謝! – 2012-02-20 15:49:34