Группировка значений по неделям в адате с использованием Linq to SQL или обычного SQL - PullRequest
1 голос
/ 01 апреля 2011

У меня есть таблица, которая имеет вид:

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, но если мне нужно вызвать хранимую процедуру, это нормально. На самом деле я не получил ни малейшего представления о том, как это осуществить.

Как я могу начать с этим?

UPDATE

Я закончил тем, что написал это как процедуру хранения, которая работает, но, на мой взгляд, это не очень хорошее решение.

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 голосов
/ 27 апреля 2011

Я не уверен, что понимаю, как вы ожидаете, что результат будет выглядеть.Но я постараюсь не позволить этому помешать мне сделать предложение.

Если вы создаете таблицу календаря, такие запросы, как правило, легко выразить.Но то, что вы ищете, может и не быть.(См. Ниже.)

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

Я ранее разместил код для базовой календарной таблицы (синтаксис PostgreSQL) на SO.Это не включает недели и годы ISO.Если хотите, я выложу полный код здесь позже.Просто дайте мне знать.

Две вещи, которые не выполняет этот запрос

Он не пытается рассчитать пропорциональные часы.Например, последняя строка вашего образца ввода имеет дату начала 2010-03-05.Эта дата относится к 9-й неделе ISO, которая проходит с 2010-03-01 по 2010-03-07;запрос, который я написал, не пытается рассчитать 3/7 из 9 часов для недели ISO 9.

Он не совпадает с календарем.Номера недели ISO были удобны для меня, потому что они уже были в моей календарной таблице.Если вы создаете свою собственную таблицу календаря, вы можете определить их по своему усмотрению.

...