2009-03-03 59 views
40

Trong Microsoft SQL Server, tôi có một số tuầnNhận ngày từ một số tuần trong T-SQL

(from DATEPART(wk, datecol)) 

nhưng những gì tôi muốn làm là tắt chức năng này trở lại vào khoảng ngày trong tuần đó.

Ví dụ,

SELECT DATEPART(wk, GETDATE()) 

sản lượng 10 Tôi muốn lấy 2009/03/01 và 3/7/2009 từ số này.

Điều này có khả thi không?

+1

Xem thêm: http: // stackoverflow.com/questions/1267126/how-do-you-get-the-week-start-date-and-week-end-date-from-week-number-in-sql –

Trả lời

31

câu trả lời Quassnoi của công trình, nhưng loại lá bạn phải gánh chịu dọn dẹp ngày nếu họ là số ngày trong giữa ngày (bắt đầu của mình trong tuần để lại cho bạn một ngày sớm hơn bạn cần phải nếu bạn sử dụng thời gian vào giữa ngày - bạn có thể kiểm tra bằng cách sử dụng GETDATE()).

Tôi đã sử dụng một cái gì đó như thế này trong quá khứ:

SELECT 
    CONVERT(varchar(50), (DATEADD(dd, @@DATEFIRST - DATEPART(dw, DATECOL), DATECOL)), 101), 
    CONVERT(varchar(50), (DATEADD(dd, @@DATEFIRST - DATEPART(dw, DATECOL) - 6, DATECOL)), 101) 

Một lợi ích phụ của việc này là bằng cách sử dụng @@ DATEFIRST bạn có thể xử lý tuần bắt đầu từ ngày chuẩn (mặc định là chủ nhật, nhưng với SET @@ DATEFIRST bạn có thể thay đổi điều này).

Có vẻ như điên mà thao tác cập nhật đơn giản trong SQL Server phải là phức tạp này, nhưng có bạn đi ...

+0

Um, DATECOL là cột do người dùng xác định trong ví dụ. Mã của Quassnoi chỉ dựa vào "DATEPART (ngày trong tuần", có sẵn vào năm 2000. – alyssackwan

+0

Ah, điểm tốt. Tôi đã làm sai nó lên. Tôi sẽ chỉnh sửa cho phù hợp. – mwigdahl

+0

Chỉnh sửa ở đâu mà không sử dụng DATECOL? Hãy xem câu trả lời của tôi) – Brad

3
SELECT DATECOL - DATEPART(weekday, DATECOL), DATECOL - DATEPART(weekday, DATECOL) + 7 
13

Bạn có thể đặt @WeekNum và @YearNum để bất cứ điều gì bạn muốn - trong ví dụ này, họ có nguồn gốc từ biến @datecol, được đặt thành GETDATE() cho mục đích minh họa. Một khi bạn có những values- bạn có thể tính toán phạm vi ngày trong một tuần bằng cách sử dụng như sau:

 
DECLARE @datecol datetime = GETDATE(); 
DECLARE @WeekNum INT 
     , @YearNum char(4); 

SELECT @WeekNum = DATEPART(WK, @datecol) 
    , @YearNum = CAST(DATEPART(YY, @datecol) AS CHAR(4)); 

-- once you have the @WeekNum and @YearNum set, the following calculates the date range. 
SELECT DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNum) + (@WeekNum-1), 6) AS StartOfWeek; 
SELECT DATEADD(wk, DATEDIFF(wk, 5, '1/1/' + @YearNum) + (@WeekNum-1), 5) AS EndOfWeek;
+0

Bạn có thể giải thích 6 và 5 trong DATEDIFF không? – Ben

+0

@BenAdler làm 'select cast (0 là datetime)' trả về '1900-01-01 00: 00: 00.000', vì vậy 5 và 6 phải là 5 và 6 ngày từ jan 1, 1900 tương ứng. jan 7 là ngày chủ nhật đầu tiên của năm 1900. phần còn lại của calc được hiển thị tốt hơn là giải thích: 'chọn dateiff (wk, 6, '1/1/2015');' trả về 5999 tuần kể từ 1/7/1900 'chọn datepart (wk, '23/2/2015'); 'trả về 26 tuần kể từ 1/1/2015 ' chọn dateadd (wk, 5999 + (26 - 1), 6); 'trả về: 2015-06-21 00 : 00: 00.000, chính xác là 6024 tuần kể từ ngày chủ nhật đầu tiên của năm 1900, ergo cũng là một chủ nhật – ZagNut

+0

Hai dòng cuối cùng chính xác những gì chúng tôi cần! Chỉ thay đổi 5 và 6 vì tuần bắt đầu vào thứ hai và kết thúc vào chủ nhật ở đây. \t DATEADD (wk, DATEDIFF (wk, 6, '1/1 /' + CAST (pr.Jaar as nvarchar)) + (pr.Week-1), 7) AS StartOfWeek, \t DATEADD (wk, DATEDIFF (wk, 5, '1/1 /' + CAST (pr.Jaar là nvarchar)) + (pr.Week-1), 6) AS EndOfWeek – Rob

0
SELECT DATEADD(week, @weekNumber - 1, DATEADD(DAY, @@datefirst - DATEPART(weekday, CAST(YEAR(GETDATE()) AS VARCHAR) + '-01-01') - 6, CAST(YEAR(GETDATE()) AS VARCHAR) + '-01-01')) 
1

này nên làm việc bất kể @@DATEFIRST

ALTER FUNCTION dbo.DEV_VW_WeekSerial 
    (@YearNum int, 
    @WeekNum int, 
    @DayNum int) 
    RETURNS Date AS 

    BEGIN 

     DECLARE @FirstDayYear As Date; 

     SET @FirstDayYear='01/01/' + CAST(@YearNum As varchar) 

     RETURN dateadd(d,(@DayNum-datepart(weekday,@FirstDayYear)),dateadd(week, @WeekNum-1,@FirstDayYear)) 

    END 
0
DECLARE @dayval int, 
@monthval int, 
@yearval int 

SET @dayval = 1 
SET @monthval = 1 
SET @yearval = 2011 


DECLARE @dtDateSerial datetime 

     SET @dtDateSerial = DATEADD(day, @dayval-1, 
           DATEADD(month, @monthval-1, 
            DATEADD(year, @yearval-1900, 0) 
           ) 
          ) 

DECLARE @weekno int 
SET @weekno = 53 


DECLARE @weekstart datetime 
SET @weekstart = dateadd(day, 7 * (@weekno -1) - datepart (dw, @dtDateSerial), @dtDateSerial) 

DECLARE @weekend datetime 
SET @weekend = dateadd(day, 6, @weekstart) 

SELECT @weekstart, @weekend 
3

Làm thế nào về một chức năng nhảy đến tuần trước số tuần đó và sau đó thực hiện các bước trong vài ngày tới cho đến khi số tuần thay đổi (tối đa 7 bước), trả về ngày mới?

CREATE FUNCTION dbo.fnGetDateFromWeekNo 
(@weekNo int , @yearNo int) 
RETURNS smalldatetime 
AS 
BEGIN 

DECLARE @tmpDate smalldatetime 


set @tmpdate= cast(cast (@yearNo as varchar) + '-01-01' as smalldatetime) 
-- jump forward x-1 weeks to save counting through the whole year 
set @tmpdate=dateadd(wk,@weekno-1,@tmpdate) 

-- make sure weekno is not out of range 
if @WeekNo <= datepart(wk,cast(cast (@yearNo as varchar) + '-12-31' as smalldatetime)) 
BEGIN 
    WHILE (datepart(wk,@tmpdate)<@WeekNo) 
    BEGIN 
     set @tmpdate=dateadd(dd,1,@tmpdate) 
    END 
END 
ELSE 
BEGIN 
    -- invalid weeknumber given 
    set @tmpdate=null 
END 


RETURN @tmpDate 

END 
+1

Tuyệt vời! nhưng tôi muốn chỉnh sửa bộ @ tmpdate = dateadd (wk, @ weekno-2, @ tmpdate) – sebacipo

+0

Sebacipo đã đúng ngay ngày đầu tiên của Tuần 1 có thể là vào tháng 12 của năm trước. Ngoài ra, xác nhận là không chính xác nếu ngày cuối cùng trong năm là tuần 1. Cảm ơn bạn đã chia sẻ mặc dù .... điều này là hoàn hảo, với một vài tweeks – Ian

1
dateadd(
    dd, 
    datepart(wk, @Date)*7, 
    convert(smalldatetime, convert(char,year(max(@Date)))+convert(char, '-01-01')) 
)-1 
1

Ở đây bạn chỉ phải vượt qua năm và tuần số.

DECLARE @Year VARCHAR(4) 

SET @Year= '2012' 

DECLARE @FirstDate DATETIME 

SET @FirstDate = (SELECT DATEADD(dd,1,(SELECT DATEADD(wk,DATEPART(wk,GETDATE())-1,Convert(DAteTime,'01-01-' + @Year)))) 
       ) 
DECLARE @LastDate DATETIME 

SET @LastDate =(SELECT DATEADD(dd,4,@FirstDate)) 

SELECT @FirstDate 
     ,@LastDate 
1

Để trả lời câu hỏi của bạn:

--CHANGE A WEEK NUMBER BACK INTO A DATE FOR THE FIRST DATE OF THE WEEK 
DECLARE @TaskWeek INT = 17 
DECLARE @TaskYear INT = 2013 

SELECT DATEADD(WEEK, @TaskWeek - 1,DATEADD(dd, 1 - DATEPART(dw, '1/1/' + CONVERT(VARCHAR(4),@TaskYear)), '1/1/' + CONVERT(VARCHAR(4),@TaskYear))) 
3

Nếu tuần của bạn bắt đầu từ thứ hai (trên SQL Server 2008)

select datecol, 
    DATEPART(ISOWK, datecol) as week, 
    ((DATEPART(dw, datecol)+5)%7)+1 as weekday, 
    (DATEADD(dd, -((DATEPART(dw, datecol)+5)%7), datecol)) as Monday, 
    (DATEADD(dd, -((DATEPART(dw, datecol)+5)%7)+6, datecol)) as Sunday 
0

Trả lời:

select DateAdd(day,-DATEPart(DW,<Date>), <Date>) [FirstDayOfWeek] ,DateAdd(day,-DATEPart(DW,<Date>)+6, <Date>) [LastDayOfWeek] 
FROM <TABLE> 
1

Tôi đã thực hiện giải pháp của elindeblom và sửa đổi nó - việc sử dụng các chuỗi (ngay cả khi được đưa vào các ngày) khiến tôi lo lắng về các định dạng ngày khác nhau được sử dụng trên khắp thế giới. Điều này tránh được vấn đề đó.

Mặc dù không được yêu cầu, tôi cũng đã bao gồm thời gian để tuần kết thúc 1 giây trước nửa đêm:

DECLARE @WeekNum INT = 12, 
     @YearNum INT = 2014 ; 

    SELECT DATEADD(wk, 
        DATEDIFF(wk, 6, 
          CAST(RTRIM(@YearNum * 10000 + 1 * 100 + 1) AS DATETIME)) 
        + (@WeekNum - 1), 6) AS [start_of_week], 
      DATEADD(second, -1, 
        DATEADD(day, 
          DATEDIFF(day, 0, 
            DATEADD(wk, 
              DATEDIFF(wk, 5, 
                 CAST(RTRIM(@YearNum * 10000 
                   + 1 * 100 + 1) AS DATETIME)) 
              + (@WeekNum + -1), 5)) + 1, 0)) AS [end_of_week] ; 

Vâng, tôi biết tôi vẫn đang đúc nhưng từ một số. Nó "cảm thấy" an toàn hơn với tôi.

này kết quả trong:

start_of_week   end_of_week 
    ----------------------- ----------------------- 
    2014-03-16 00:00:00.000 2014-03-22 23:59:59.000 
1

Give it @year và @Week, trở lại ngày đầu tiên của tuần đó.

Declare @Year int 
,@Week int 
,@YearText varchar(4) 

set @Year = 2009 
set @Week = 10 

set @YearText = @Year 

print dateadd(day 
      ,1 - datepart(dw, @YearText + '-01-01') 
       + (@Week-1) * 7 
      ,@YearText + '-01-01') 
1

Tôi chỉ đưa SELECT với một tuyên bố CASE (Đối với hoàn cảnh của tôi thứ hai đánh dấu ngày đầu tiên của tuần, và không muốn để đối phó với lệnh SET DATEFIRST:

CASE DATEPART(dw,<YourDateTimeField>) 
    WHEN 1 THEN CONVERT(char(10), DATEADD(DD, -6, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), <YourDateTimeField>,126) 
    WHEN 2 THEN CONVERT(char(10), <YourDateTimeField>,126) + ' to ' + CONVERT(char(10), DATEADD(DD, 6, <YourDateTimeField>),126) 
    WHEN 3 THEN CONVERT(char(10), DATEADD(DD, -1, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 5, <YourDateTimeField>),126) 
    WHEN 4 THEN CONVERT(char(10), DATEADD(DD, -2, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 4, <YourDateTimeField>),126) 
    WHEN 5 THEN CONVERT(char(10), DATEADD(DD, -3, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 3, <YourDateTimeField>),126) 
    WHEN 6 THEN CONVERT(char(10), DATEADD(DD, -4, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 2, <YourDateTimeField>),126) 
    WHEN 7 THEN CONVERT(char(10), DATEADD(DD, -5, <YourDateTimeField>),126) + ' to ' + CONVERT(char(10), DATEADD(DD, 1, <YourDateTimeField>),126) 
    ELSE 'UNK' 
END AS Week_Range 
0

này làm việc cho tôi:

select 
    convert(varchar(50), dateadd(dd, - datepart(dw, DATECOL) + 1, DATECOL), 101), 
    convert(varchar(50), dateadd(dd, - datepart(dw, DATECOL) + 7, DATECOL), 101) 
0

tôi không dành thời gian để kiểm tra tất cả các câu trả lời trên đây, nhưng không có vẻ như đơn giản và hiệu quả như này:

DECLARE @WeekNum int 
DECLARE @YearNum char(4) 

SELECT DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNum) + (@WeekNum-1), 6) AS StartOfWeek 

SELECT DATEADD(wk, DATEDIFF(wk, 5, '1/1/' + @YearNum) + (@WeekNum-1), 5) AS EndOfWeek 
1

Câu trả lời bình chọn nhiều nhất hoạt động ngoại trừ Tuần đầu tiên và tuần trước trong năm. Khi datecol giá trị'2009/01/01', kết quả sẽ là 2009/01/032008/12/28.

Giải pháp của tôi:

DECLARE @Date date = '2009-03-01', @WeekNum int, @StartDate date; 
SELECT @WeekNum = DATEPART(WEEK, @Date); 
SELECT @StartDate = DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)); 
SELECT CONVERT(nvarchar, CASE WHEN @WeekNum = 1 THEN CAST(DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0) AS date) ELSE DATEADD(DAY, 7 * @WeekNum, @StartDate) END, 101) AS StartOfWeek 
     ,CONVERT(nvarchar, CASE WHEN @WeekNum = DATEPART(WEEK, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date) + 1, 0))) THEN DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date) + 1, 0)) ELSE DATEADD(DAY, 7 * @WeekNum + 6, @StartDate) END, 101) AS EndOfWeek; 

này sẽ hiển thị 01/01/20092009/01/03 trong tuần 1, và hiển thị 2009/03/0103/07/2009 cho tuần thứ 10.

Tôi nghĩ rằng đây sẽ là những gì bạn muốn chính xác. Bạn có thể thay thế các biến bằng các biểu thức của chúng như bạn muốn.

Các vấn đề liên quan