Получить даты из номера недели в T-SQL - PullRequest
45 голосов
/ 03 марта 2009

В Microsoft SQL Server у меня есть номер недели

(from DATEPART(wk, datecol)) 

но я бы хотел превратить это обратно в диапазон дат на эту неделю.

Например,

SELECT DATEPART(wk, GETDATE())

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

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

Ответы [ 19 ]

31 голосов
/ 03 марта 2009

Ответ 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 должны быть такими загадочными, но вы идете ...

17 голосов
/ 09 ноября 2009

Вы можете установить для @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;
4 голосов
/ 17 сентября 2013

Если ваша неделя начинается с понедельника (в 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
4 голосов
/ 17 апреля 2013

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

--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 голосов
/ 03 марта 2009
SELECT DATECOL - DATEPART(weekday, DATECOL), DATECOL - DATEPART(weekday, DATECOL) + 7
3 голосов
/ 31 января 2012

Как насчет функции, которая переходит на неделю до номера этой недели, а затем переходит на следующие несколько дней, пока не изменится номер недели (не более 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 голос
/ 27 сентября 2018
declare @IntWeek as varchar(20)
SET @IntWeek = '201820'

SELECT 
    DATEADD(wk, DATEDIFF(wk, @@DATEFIRST, LEFT(@IntWeek,4) + '-01-01') +
    (cast(RIGHT(@IntWeek, 2) as int) -1), @@DATEFIRST) AS StartOfWeek
1 голос
/ 28 марта 2017

Ответ большинства голосов работает отлично, за исключением 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-ю неделю.

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

1 голос
/ 30 июня 2015

Я только что включил SELECT с оператором CASE (Для моей ситуации понедельник отметил первый день недели и не хотел иметь дело с командой 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
1 голос
/ 25 марта 2014

Дайте это @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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...