2010-07-26 7 views
4

У меня есть запрос (для использования в bug tracker.net), который вычисляет количество ошибок по неделям по статусу. Но запрос возвращает номер недели, что я действительно хочу это первая дата неделиSQL Server - получить первую дату через неделю, учитывая номер недели?

select datepart(wk, DateAdd(day, 0, DateDiff(day, 0, bg_reported_date))) 
     as [week], bg_status , st_name as [status], count(*) as [count] 
    from bugs inner join statuses on bg_status = st_id 
group by datepart(wk, DateAdd(day, 0, DateDiff(day, 0, bg_reported_date))), 
      bg_status, st_name 
order by [week], bg_status 

Та часть, которая получает номер недели является

datepart(wk, DateAdd(day, 0, DateDiff(day, 0, bg_reported_date))) as [week] 

возвращает этот вывод:

week  bg_status status          count 
----------- ----------- --------------------------------------------- ------ 
22   1   new           1 
22   5   closed          32 

Но было бы лучше сказать первую дату каждой недели, например 01-01-2010, затем 08-01-2010 и т. Д.

Вопрос не дубликат How do you get the "week start date" and "week end date" from week number in SQL Server? (ответ говорит как получить недельное начало от даты не от номера недели)

Не дубликат Calculate date from week number (вопроса просит C#)

Не дубликат Get first date of week from provided date (вопрос просит JavaScript)

я искать, но не смог найти ответил на SQL Server (2010 г. этот вопрос, если это имеет значение)

+0

Что делает 'DateAdd (день, 0, DateDiff (день, 0, bg_reported_date))' do? Я подозреваю, что это может быть упрощено. – Gabe

+0

@Gabe: Я думаю, что внутренний DateDiff() вычисляет количество дней между «датой 0» и сообщенной датой ошибки.Внешняя DateAdd() затем добавляет это количество дней в 'date 0', давая значение DATE (или, возможно, значение DATETIME с 0 часами, 0 минутами, 0 секундами). Если это можно упростить, я думаю, что упрощение может быть «CAST (bg_reported_date AS DATE)», как используется в выражении «начало недели». –

+0

Джонатан: Это то, что я думал, но не имеет смысла, почему вы использовали бы это при вызове 'DATEPART'. Все времена на данной дате всегда должны возвращать тот же номер недели. – Gabe

ответ

5

Если вы думаете об этом в правильном направлении, ответ на SO 1267126 может быть применен к вашей проблеме.

Каждая ошибка, о которой сообщалось в группе, отображается на той же неделе. Поэтому по определению каждая из этих дат ошибок должна также отображаться в одно и то же начало недели. Таким образом, вы запускаете расчет «начало недели с заданной даты» в датах отчета об ошибках, а также вычисляете число недель и группируете оба (скромно ужасные) выражения и получаете ответ, который вы ищете.

SELECT DATEPART(wk, DATEADD(day, 0, DATEDIFF(d, 0, bg_reported_date))) [week], 
     DATEADD(dd, -(DATEPART(dw, bg_reported_date)-1), bg_reported_date) 
     AS [weekstart], bg_status, st_name AS [status], COUNT(*) AS [count] 
    FROM bugs INNER JOIN statuses ON bg_status = st_id 
GROUP BY DATEPART(wk, DATEADD(day, 0, DATEDIFF(day, 0, bg_reported_date))), 
     DATEADD(dd, -(DATEPART(dw, bg_reported_date)-1), bg_reported_date), 
     bg_status, st_name 
ORDER BY [week], bg_status 

Поскольку bg_reported_date является DATETIME (см комментарий, она включает в себя компонент времени), то необходимо, чтобы привести его к DATE перед определением уик-старт (но выражение номер недели не нужен бросок, и «день недели» часть выражения начала недели не нужен актерский либо):

SELECT DATEPART(wk, DATEADD(day, 0, DATEDIFF(d, 0, bg_reported_date))) [week], 
     DATEADD(dd, -(DATEPART(dw, bg_reported_date)-1), 
       CAST(bg_reported_date AS DATE)) AS [weekstart], 
     bg_status, st_name AS [status], COUNT(*) AS [count] 
    FROM bugs INNER JOIN statuses ON bg_status = st_id 
GROUP BY DATEPART(wk, DATEADD(day, 0, DATEDIFF(day, 0, bg_reported_date))), 
     DATEADD(dd, -(DATEPART(dw, bg_reported_date)-1), 
       CAST(bg_reported_date AS DATE), 
     bg_status, st_name 
ORDER BY [week], bg_status 

NB: неопробованный код!

+0

Это неправильно группируется, потому что bg_reported_date включает время. Я посмотрю, что произойдет, когда время будет удалено первым. Это сделает это выражение намного хуже - bg_reported_date находится там 3 раза, поэтому вам нужно будет удалить время 3 раза. –

+0

Сладкий, спасибо. Его уродливая группа DATETHIS и DATETHAT функционирует, но отлично работает. –

0

Я понимаю, что это очень старая тема, но «Получить первое свидание через неделю, учитывая номер недели», это именно то, что я хотел сделать, и у меня нет фактической даты для работы, поэтому принятый ответ не будет работать для меня. Я думал, что отправлю свое решение для потомков. Обратите внимание, что я подозреваю, что разные настройки культуры МОГУТ это сломать, поэтому перед использованием.

Мой ответ построен начиная с this один.

Предположим, вы знаете номер недели и год, и вы хотите получить даты начала и окончания той недели того года. Вот что у меня есть:

--These 2 "declared" variables would be passed in somehow 
declare @WeekNumber int = DATEPART(wk, GETDATE()) 
declare @ForYear int = YEAR(GETDATE())-1 

--Since we don't have a raw date to work with, I figured I could just start with 
--Jan 1 of that year. I'll store that date in a cte here, but if you are doing this 
--in a stored proc or function, it would make much more sense to use another @variable 
;with x as 
(
    --this method works in SQL 2008: 
    SELECT CONVERT(DateTime, ('1/1/' + CONVERT(varchar, @ForYear))) as Jan1ForSelectedYear 
    --If you are using 2014 or higher, you can use this instead: 
    --DATETIME2FROMPARTS(@ForYear, 1, 1, 0,0,0,0,0) 
) 
--Now that we have a date to work with, we'll just add the number of weeks to that date 
--That will bring us to the right week number of the given year. 
--Once we have THAT date, we can get the beginning and ending of that week 
--Sorry to make you scroll, but I think this is easier to see what is going on this way 
SELECT CONVERT(varchar(50), DateAdd(wk, (@WeekNumber - 1), (DATEADD(dd, @@DATEFIRST - DATEPART(dw, x.Jan1ForSelectedYear) - 6, x.Jan1ForSelectedYear))), 101) as FirstDayOfWeekXForSelectedYear, 
     CONVERT(varchar(50), DateAdd(wk, (@WeekNumber - 1), (DATEADD(dd, @@DATEFIRST - DATEPART(dw, x.Jan1ForSelectedYear) , x.Jan1ForSelectedYear))), 101) as LastDayOfWeekXForSelectedYear 
FROM x 
Смежные вопросы