2009-03-03 4 views
40

В Microsoft SQL Server, у меня есть номер неделиПолучить даты с номером недели в T-SQL

(from DATEPART(wk, datecol)) 

но то, что я хотел бы сделать, это превратить это обратно в пролете дату на этой неделе.

Например,

SELECT DATEPART(wk, GETDATE()) 

выходы 10. Я хотел бы извлечь 3/1/2009 и 3/7/2009 из этого числа.

Возможно ли это?

+1

См. Также: http: // stackoverflow.com/questions/1267126/how-do-you-get-the-week-start-date-and-week-end-date-from-week-number-in-sql –

ответ

31

ответ Quassnoi работает, но вид оставляет вас на крючок для очистки даты, если они даты в середине дня (его начало недели оставляет вас один день раньше, чем вы должны быть, если вы используете время в середине дня - вы можете проверить с помощью GETDATE()).

Я использовал что-то подобное в прошлом:

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

Побочным эффектом этого является то, что с помощью @@ DATEFIRST вы можете справиться с нестандартными неделю начиная дней (по умолчанию это воскресенье, но с SET @@ DATEFIRST вы можете это изменить).

кажется сумасшедшим, что просто дата манипуляции в SQL Server должен быть этот аркан, но там вы идете ...

+0

Um, DATECOL - это определяемый пользователем столбец в пример. Код Quassnoi основывается только на «DATEPART (будний день», который доступен в 2000 году. – alyssackwan

+0

А, хорошо, я перепутал это. Я отредактирую это. – mwigdahl

+0

Где редактирование без использования DATECOL? См. Мой ответ – Brad

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

Вы можете установить @WeekNum и @YearNum на то, что вы хотите - в этом примере они являются производными из переменной @datecol, для которой установлено значение GETDATE(). Если у вас есть те, с ценностно можно рассчитать диапазон дат в течение недели с помощью следующих действий:

 
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

Не могли бы вы объяснить, что 6 и 5 для DATEDIFF? – Ben

+0

@BenAdler делает 'select cast (0 as datetime)' возвращает '1900-01-01 00: 00: 00.000', поэтому 5 и 6 должны быть 5 и 6 дней с 1 января 1900 года соответственно. jan 7 является первым воскресеньем 1900 года. Остаток calc лучше показан, чем объясняется: 'select lateiff (wk, 6, '1/1/2015');' возвращает 5999 недель с 1/7/1900 'select datepart (wk, '6/23/2015'); 'возвращает 26 недель с 01.01.2005 ' select dateadd (wk, 5999 + (26 - 1), 6); 'возвращает: 2015-06-21 00 : 00: 00.000, что ровно 6024 недели с первого воскресенья 1900 года, ergo также воскресенье – ZagNut

+0

Последние две строки, где именно то, что нам нужно! Только изменили 5 и 6, потому что недели начинаются в понедельник и заканчиваются в воскресенье здесь. \t DATEADD (WK, DATEDIFF (WK, 6, '1/1 /' + CAST (pr.Jaar, как NVARCHAR)) + (pr.Week-1), 7) А.С. StartOfWeek, \t DATEADD (WK, DATEDIFF (wk, 5, '1/1 /' + CAST (пр.Джаар как nvarchar)) + (пр.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

Это должно работать независимо от @@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

Как насчет функции который перескакивает на неделю до номера этой недели, а затем проходит через следующие несколько дней, пока номер недели не изменится (максимум 7 шагов), вернув новую дату?

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

Отлично! но мне нужно отредактировать set @ tmpdate = dateadd (wk, @ weekno-2, @ tmpdate) – sebacipo

+0

Sebacipo был прав, поскольку первый день недели 1 может быть в декабре прошлого года. Кроме того, проверка неверна, если последний день в году - неделя 1. Спасибо за обмен хотя .... это прекрасно, с несколькими твиками – Ian

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

Здесь вы просто должны пройти год и номер недели.

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

Чтобы ответить на ваш вопрос:

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

Если неделя начинается с понедельника (по 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

Ответ:

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

Я принял решение elindeblom и изменил его - использование струн (даже если их отливать до дат) заставляет меня нервничать в разных форматах дат, используемых во всем мире. Это позволяет избежать этой проблемы.

Пока не просил, я также включил время так неделю заканчивается 1 секунду до полуночи:

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] ; 

Да, я знаю, что я до сих пор кастинг, но из ряда. Он «чувствует» себя более безопасным для меня.

Это приводит к:

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

Дайте ему @Year и @Week, вернуть первую дату этой недели.

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

Я просто вобрал в себя ВЫБРАТЬ с сазом (Для моей ситуации понедельника был первый день недели, и не хочу иметь дело с командой 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

Это работает для меня:

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

я не брал время, чтобы проверить каждый ответ на здесь, но ничего, кажется, столь же просто и так эффективно, как это:

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

Наиболее голосов ответ работает отлично, за исключением 1-й недели и на прошлой неделе года. Когда datecol значение «2009-01-01», результат будет 01/03/2009 и 12/28/2008.

Мое решение:

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; 

Это покажет 01.01.2009 и 01/03/2009 на 1-й недели, и дисплей 03/01/2009 и 03/07/2009 на 10-ю неделю.

Я думаю, что это именно то, что вы хотите точно. Вы можете заменить переменные своими выражениями по своему усмотрению.

Смежные вопросы