Получать даты с номера недели в T-SQL
В Microsoft SQL Server у меня есть номер недели
(from DATEPART(wk, datecol))
но то, что я хотел бы сделать, это вернуть его обратно в промежуток времени на эту неделю.
Например,
SELECT DATEPART(wk, GETDATE())
дает 10. Я бы хотел получить от этого номера 3/1/2009 и 3/7/2009.
Возможно ли это?
Ответы
Ответ 1
Ответ 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 должна быть такой загадочной, но там вы идете...
Ответ 2
Вы можете настроить @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;
Ответ 3
SELECT DATECOL - DATEPART(weekday, DATECOL), DATECOL - DATEPART(weekday, DATECOL) + 7
Ответ 4
Как насчет функции, которая перескакивает на неделю до номера недели, а затем выполняет следующие несколько дней, пока номер недели не изменится (максимум 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
Ответ 5
Если ваша неделя начинается с понедельника (на 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
Ответ 6
Это должно работать независимо от @@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
Ответ 7
dateadd(
dd,
datepart(wk, @Date)*7,
convert(smalldatetime, convert(char,year(max(@Date)))+convert(char, '-01-01'))
)-1
Ответ 8
Здесь вам просто нужно указать номер года и недели.
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
Ответ 9
Чтобы ответить на ваш вопрос:
--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)))
Ответ 10
Я принял решение 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
Ответ 11
Дайте @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')
Ответ 12
Я просто включил 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
Ответ 13
Ответ большинства голосов работает отлично, за исключением первой недели и последней недели года. Когда значение datecolor '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-й неделе.
Я думаю, что это именно то, что вы хотите точно. Вы можете заменить переменные своими выражениями, как хотите.
Ответ 14
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'))
Ответ 15
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
Ответ 16
Ответ:
select DateAdd(day,-DATEPart(DW,<Date>), <Date>) [FirstDayOfWeek] ,DateAdd(day,-DATEPart(DW,<Date>)+6, <Date>) [LastDayOfWeek]
FROM <TABLE>
Ответ 17
Это работает для меня:
select
convert(varchar(50), dateadd(dd, - datepart(dw, DATECOL) + 1, DATECOL), 101),
convert(varchar(50), dateadd(dd, - datepart(dw, DATECOL) + 7, DATECOL), 101)
Ответ 18
Я не нашел времени, чтобы проверить каждый ответ здесь, но ничего не кажется таким простым и эффективным, как это:
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