使用Linq to SQL或纯SQL将日期范围内的值分组为几周

时间:2011-04-01 11:10:13

标签: sql linq-to-sql date-range

我有一个表格形式:

StartDate[date], EndDate[date], HoursPerWeek[int]

并且有点像这样:

StartDate  |   EndDate  | HoursPerWeek
01/01/2010 | 31/12/2010 | 37
01/01/2010 | 31/03/2010 | 16
05/03/2010 | 31/10/2010 | 9

我需要生成的是一个表格,该表格按周给出了给定日期范围内工作小时数的细分。

理想情况下我会在linq to sql中执行此操作,但是如果我需要调用一个很好的存储过程。我还没有真正了解如何实现这一目标。

我怎样才能开始这个?

更新

我最终把它写成了一个商店程序,这个程序很有效,但对我来说这不是一个很好的解决方案。

CREATE PROCEDURE prcGetHoursWorked
(
    @StartDate DATE,
    @EndDate DATE
)
AS

CREATE TABLE #Results
(
    WeekStart DATE,
    TotalHours INT
)

DECLARE @WeekOffset INT
DECLARE @FirstDayOfStartWeek DATE
DECLARE @HoursThisWeek INT

SET @WeekOffset = 0
SET @FirstDayOfStartWeek = dbo.fnc_StartOfWeek(@StartDate, 2);

WHILE (DATEDIFF(wk, @StartDate, @EndDate) > @WeekOffset)
BEGIN
    SELECT @HoursThisWeek = SUM(HoursPerWeek) FROM StaffCost
    WHERE NOT (
                Start> DATEADD(wk, @WeekOffset + 1, @FirstDayOfStartWeek) 
                OR 
                [End] < DATEADD(wk, @WeekOffset, @FirstDayOfStartWeek)
            )

    INSERT INTO #Results
    VALUES(DATEADD(wk, @WeekOffset, @FirstDayOfStartWeek), @HoursThisWeek)

    SET @WeekOffset = @WeekOffset + 1
END

SELECT * FROM #Results

是否可以将此作为基于集合的操作,或者更好的直接从linq到sql?

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解您对输出的期望。但我会尽量不让这阻止我提出建议。

如果您构建日历表,则此类查询通常很容易表达。但你正在寻找的可能不是。 (见下文。)

select c.cal_date as week_end, c.iso_year, c.iso_week, 
       sum(hoursperweek) as hours_this_week
from st
inner join calendar c on (c.cal_date >= startdate and 
                          c.cal_date <= enddate and 
                          c.day_of_week = 'Sun')
group by week_end, iso_year, iso_week
order by week_end

Heres是输出的一部分。我修剪了它。

week_end     iso_year   iso_week  hours_this_week
--
2010-01-03   2009       53        53
...
2010-02-21   2010        7        53
2010-02-28   2010        8        53
2010-03-07   2010        9        62
2010-03-14   2010       10        62
2010-03-21   2010       11        62
2010-03-28   2010       12        62
2010-04-04   2010       13        46
2010-04-11   2010       14        46
...

我之前在SO上发布了code for a basic calendar table(PostgreSQL语法)。它不包括ISO周和年。如果你愿意,我会在稍后发布完整的代码。请告诉我。

此查询未执行的两件事

它不会尝试按比例计算小时数。例如,样本输入的最后一行的开始日期为2010-03-05。那个日期属于ISO第9周,从2010-03-01到2010-03-07;我写的查询并没有尝试计算ISO第9周的9小时3/7。

它与日历不对齐。 ISO周数对我来说很方便,因为它们已经在我的日历表中了。如果您构建自己的日历表,则可以按照自己喜欢的方式定义它们。