我有一个表格形式:
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?
答案 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周数对我来说很方便,因为它们已经在我的日历表中了。如果您构建自己的日历表,则可以按照自己喜欢的方式定义它们。