在 Linq to SQL 中按周分组(周数)。

6
在常规的SQL中,我可以做一些像这样的操作:
SELECT * From T GROUP BY DATEPART(wk, T.Date)

我该如何在Linq to SQL中实现这个功能?

以下方法均无法实现:

From F In DB.T Group R By DatePart(DateInterval.WeekOfYear, F.Date)

也不要工作:
From F In DB.T Group R By (F.Date.DayOfYear / 7)

当你说它不起作用时,你指的是什么?无法编译,没有返回预期结果? - sgriffinusa
无法编译...“范围变量名称只能从没有参数的简单或限定名称中推断出。” - ariel
好的,答案是“从F在DB.T组中按照WeekOfYear = (F.Date.DayOfYear / 7)进行分组”。 - ariel
6个回答

8

LINQ to SQL 不支持 Calendar.WeekOfYear 方法,但是您可以潜在地创建一个 TSQL 函数,包装对 DatePart 的调用。DayOfYear / 7 技巧适用于大多数情况,并且更容易使用。这是我最终得到的代码:

var x = from F in DB.T
        group F by new {Year = F.Date.Year, Week = Math.Floor((decimal)F.Date.DayOfYear / 7)} into FGroup
        orderby FGroup.Key.Year, FGroup.Key.Week
        select new {
            Year = FGroup.Key.Year,
            Week = FGroup.Key.Week,
            Count = FGroup.Count()
        };

结果如下:

Year    Week    Count
2004    46      3
2004    47      3
2004    48      3
2004    49      3
2004    50      2
2005    0       1
2005    1       8
2005    2       3
2005    3       1
2005    12      2
2005    13      2

2
请记住,这不会直接对应于日历周,因为它假定一年始终从星期日开始。要完全匹配,您需要使用Calendar.WeekOfYear或将DatePart调用包装到SQL函数中。 - Greg Bray

2
您可以使用位于 System.Data.Entity.SqlServer 命名空间中的 SqlFunctions.DatePart 方法。
// Return the week number
From F In DB.T Group R By SqlFunctions.DatePart("week", F.Date)

1

这个工作正常。

from F in DB.T group F by F.Date.DayOfYear / 7;

你的分组方式有误。这段代码的结果将会是一个对象集合。每个对象都会有一个键(Key)属性,该属性的值就是你所分组的依据(在这个例子中是 F.Date.DayOfYear / 7 的结果)。每个对象都会包含符合分组条件的 T 对象的集合。

我所要做的就是 "From F In DB.T Group R By WeekOfYear = (F.Date.DayOfYear / 7)" ;) - ariel


0

首先,您应该获取本周第一天的日期。

要获取本周第一天的日期, 您可以使用以下代码:

public static class DateTimeExtensions
{
    public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
    {
        int diff = dt.DayOfWeek - startOfWeek;
        if (diff < 0)
        {
            diff += 7;
        }
        return dt.AddDays(-1 * diff).Date;
    }
}

然后您可以按周的第一天进行分组。

因此,这段常规 SQL 代码:

SELECT * From T GROUP BY DATEPART(wk, T.Date)

可以在 Linq to SQL 中这样完成

T.GroupBy(i => i.Date.StartOfWeek(DayOfWeek.Monday));

0
如果您关注所处的文化,以下代码将考虑这一点:
var ci = CultureInfo.CurrentCulture;
var cal = ci.Calendar;
var rule = ci.DateTimeFormat.CalendarWeekRule;
var firstDayOfWeek = ci.DateTimeFormat.FirstDayOfWeek;

var groups = from F in DB.T
             group F by cal.GetWeekOfYear(F, rule, firstDayOfWeek) into R
             select R;

这个不起作用--“方法'Int32 GetWeekOfYear(System.DateTime, System.Globalization.CalendarWeekRule, System.DayOfWeek)'没有支持到SQL的翻译。” - ariel
似乎在Linq2Sql或Linq to Entities中不支持Calendar.GetWeekOfYear函数;您需要先将整个数据集提取出来,然后再使用cal.GetWeekOfYear(x, rule, firstDayOfWeek)函数。 - Richard Slater
是的,但将DayOfYear除以7对我的需求已经足够了。谢谢! - ariel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接