2010-07-26 158 views
4

我有一個查詢(用於bug tracker.net),它按周狀態計算每週的bug數量。但是,該查詢返回的週數,我真正想要的是一週的第一天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,那麼2010年8月1日,等

問題不是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(day,0,DateDiff(day,0,bg_reported_date))'做什麼?我懷疑它可以被簡化。 – Gabe 2010-07-26 05:27:09

+0

@Gabe:我認爲內部的DateDiff()計算'date 0'和bug報告日期之間的天數。外部的DateAdd()然後將該天數添加到'日期0',給出DATE值(或者可能是0小時0分鐘0秒的DATETIME值)。如果這可以簡化,我認爲簡化可能是'CAST(bg_reported_date AS DATE)',如'星期開始'表達式中所用。 – 2010-07-26 06:20:40

+0

Jonathan:這就是我的想法,但沒有任何意義,爲什麼你會在調用'DATEPART'時使用它。在給定日期的所有時間總是應該返回同一周的數字。 – Gabe 2010-07-26 06:39:58

回答

5

如果你以正確的方式想想,答案SO 1267126可以應用到你的問題。

每個bug報告日期,你在組中映射到同一周。因此,根據定義,這些錯誤日期中的每一個還必須映射到同一周的開始。所以,你在錯誤報告日期以及週數計算上運行「從給定日期算起的一週的開始」計算,並且通過兩個(適度可怕的)表達式來分組,並最終得到你所尋求的答案。

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(但週數expression不需要投,及本週開始表達的一部分「星期幾」不需要投其一):

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 

注:未經測試的代碼!

+0

這是不正確的分組,因爲bg_reported_date包含時間。我會先看看什麼時候被刪除。它會使表達更糟糕 - bg_reported_date在那裏3次,所以必須將時間刪除3次。 – 2010-07-26 02:34:15

+0

甜,謝謝。它是一個醜陋的DATETHIS和DATETHAT函數,但效果很好。 – 2010-07-26 05:06:49

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 
相關問題