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

发布于 2024-10-29 12:59:12 字数 1358 浏览 1 评论 0原文

我有一个表格,其形式为:

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?

I have a table that is of the form:

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

and is filled a bit like this:

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

What I need to produce is a table that gives a breakdown on a week by week basis of the number of hours worked for a given date range.

Ideally I'd do this in linq to sql, but if I need to call a stored procedure that's fine. I haven't really got the first clue how to go about implementing this.

How can I get started with this?

UPDATE

I've ended up writing this as a store procedure, which works, but to my eyes is not a pretty solution.

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

Is it possible to do this as a set based operation, or better still straight from linq to sql?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不在是我 2024-11-05 12:59:12

我不确定我是否理解您期望的输出是什么样子。但我会尽力不让这阻止我提出建议。

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

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

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

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 上的表 (PostgreSQL 语法)。它不包括 ISO 周和年。如果您愿意,我稍后会在这里发布完整的代码。请告诉我。

此查询不执行的两件事

它不会尝试按比例计算小时数。例如,示例输入的最后一行的开始日期为 2010-03-05。该日期属于 ISO 第 9 周,即从 2010 年 3 月 1 日到 2010 年 3 月 7 日;我编写的查询不会尝试计算 ISO 第 9 周 9 小时的 3/7。

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

I'm not sure I understand what you expect the output to look like. But I'll try not to let that stop me from offering a suggestion.

If you build a calendar table, queries like this are generally easy to express. But what you're looking for might not be. (See below.)

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's part of the output. I trimmed it.

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
...

I've previously posted code for a basic calendar table (PostgreSQL syntax) on SO. It doesn't include ISO weeks and years. If you want, I'll post the full code here later. Just let me know.

Two things this query doesn't do

It doesn't try to calculate pro rata hours. For example, the last line of your sample input has a start date of 2010-03-05. That date falls in ISO week 9, which runs from 2010-03-01 to 2010-03-07; the query I wrote doesn't try to calculate 3/7 of 9 hours for ISO week 9.

It doesn't align with the calendar. ISO week numbers were convenient for me, because they were already in my calendar table. If you build your own calendar table, you can define them any way you like.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文