Есть ли процедура или средство для установки значения даты на основе значения недели и дня.
Для дальнейшего использования этого календарного года: 1-7 января - первая неделя, 8-14 января - вторая неделя и т. д.
Что касается значения числа дней; Понедельник 1 Вторник 2 Среда 3 Четверг 4 Пятница 5.
Используя эту логику, я хочу создать и заполнить поле даты, которое использует эти значения.
Например, я хочу, чтобы Неделя: 2 - День: 3 заполняла мое новое поле даты как 01.10.2018.
Будем очень признательны за любую помощь и руководство.


Вы можете сослаться на эту ссылку, в которой есть инструкция по созданию календарной таблицы. https://www.sqlshack.com/designing-a-calendar-table/
Что вам нужно сделать, так это сопоставить доступные столбцы, такие как год, неделя и день, с таблицей календаря и извлечь дату.
Может быть, что-то подобное поможет вам начать работу.
Он вернет дату из вашего образца, но я не тестировал во всех ситуациях ...
Так что я уверен, что потребуется некоторая настройка и использование Calender Table, как предлагает @ Ajan-Balakumaran, было бы намного лучше.
declare @year int = datepart(year, getdate())
declare @month int
declare @week int = 2
declare @day int = 3
SELECT @month = DATEPART(MM,CAST(CONVERT(CHAR(3),
DATEADD(WW, @WEEK - 1,
CONVERT(datetime, '01/01/' + CONVERT(char(4) ,@Year)))
, 100) + ' 1900' AS DATETIME))
select datefromparts(2018, @month, @day + (@week - 1) * 7)
Некоторые вещи можно сделать с помощью функций datetime, чтобы вычислить дату только по номеру недели и номеру дня недели.
Однако имейте в виду, что @@DATEFIRST на сервере может быть другим.
Которая определяет, какой день недели является первым днем недели.
Так что лучше изменить его на сеансе на 1, чтобы сделать понедельник первым днем недели.
Без этого может потребоваться корректировка в приведенных ниже расчетах.
Например, [Weekday]+1, когда select @@DATEFIRST возвращает 7
Пример фрагмента:
declare @Table table ([Week] int, [Weekday] int);
insert into @Table ([Week], [Weekday]) values
(1, 1)
,(1, 7)
,(2, 1)
,(2, 7)
;
-- The US default for @@DATEFIRST is 7, which would make Sunday weekday 1.
-- By setting @@DATEFIRST to 1 then Monday will be weekday 1
SET DATEFIRST 1;
SELECT [Week], [Weekday],
DATEADD(WEEKDAY, 1-DATEPART(WEEKDAY, DATEFROMPARTS(DATEPART(YEAR,GetDate()),1,1)), DATEADD(WEEK,[Week]-1, DATEFROMPARTS(DATEPART(YEAR,GetDate()),1,[Weekday]))) AS CalcDate
FROM @Table
ORDER BY [Week], [Weekday];
Результат:
Week Weekday CalcDate
---- ------- ----------
1 1 2018-01-01
1 7 2018-01-07
2 1 2018-01-08
2 7 2018-01-14
Обратите внимание, что год основан на текущей дате.
Но если обновить существующую таблицу?
Тогда вы могли бы посмотреть на это по-другому.
Создайте временную таблицу со всеми датами текущего года и извлеките неделю и день недели из этих дат.
Затем вы можете использовать эту временную таблицу для обновления существующей таблицы.
Пример фрагмента:
-- Create a temporary table
IF OBJECT_ID('tempdb..#tmpDates') IS NOT NULL DROP TABLE #tmpDates;
CREATE TABLE #tmpDates ([Week] INT NOT NULL, [WeekDay] INT NOT NULL, [Date] DATE NOT NULL, PRIMARY KEY ([Week], [WeekDay]));
-- Make Monday the first weekday
SET DATEFIRST 1;
-- Filling the temp table with data
WITH DATES2018 AS
(
SELECT CAST('2018-01-01' AS DATE) AS [Date]
UNION ALL
SELECT DATEADD(day, 1, [Date])
FROM DATES2018
WHERE [Date] < CAST('2018-12-31' AS DATE)
)
INSERT INTO #tmpDates ([Date], [Week], [WeekDay])
SELECT [Date], DATEPART(WEEK, [Date]) AS [Week], DATEPART(WEEKDAY, [Date]) as [WeekDay]
FROM DATES2018
ORDER BY [Week], [WeekDay]
OPTION (MAXRECURSION 366);
-- Just using a table variable per demonstration
declare @YourTable table ([Week] int, [Weekday] int, [Date] DATE);
-- Sample data
insert into @YourTable ([Week], [Weekday]) values
(1, 1)
,(1, 7)
,(2, 1)
,(2, 7)
;
-- update based on the temp table
update t
set [Date] = tmp.[Date]
from @YourTable t
join #tmpDates tmp on (tmp.[Week] = t.[Week] AND tmp.[WeekDay] = t.[Weekday])
where (t.[Date] is null OR t.[Date] <> tmp.[Date]);
select * from @YourTable;
@potatochucker Просто посмотрите, как нормально обновлять таблицу, и воспользуйтесь расчетом. Как в: update yourtable set yourfield = <put calculation here> where yourfield is null. Но если это для одноразового обновления, я бы жестко запрограммировал год вместо того, чтобы рассчитывать его из GetDate.
@potatochucker Я немного изменил расчет.
Спасибо за понимание и помощь. Я реализовал ваш код и протестировал его со своей стороны, но у меня есть проблема, когда мне нужно, чтобы это выходило за рамки одного года. У меня есть поле, в котором записывается значение года «2018», «2019» и т. д. Может ли это использоваться как средство установки общей даты без необходимости объявлять каждый данный год и вставлять его в tmpDates? Или есть способ вставить несколько лет в даты tmp? Спасибо еще раз!
@potatochucker Вам следует внимательно изучить второе решение в таблице. Вы можете установить переменные для startDate и endDate, а затем просто использовать их в SQL для #tmpDates. И переименуйте DATE2018 CTE в DATES. (потому что это звучит неправильно для дат с 2017 года; p) И установите MAXRECURSION выше или равным 0. На самом деле, вместо # временной таблицы ее можно было бы сделать постоянной таблицей с дополнительными полями, связанными с датой. Чтобы сделать его многоразовым для других запросов, обычно называется Calendar.
Теперь все работает отлично. Я сделал календарную таблицу, как вы предлагаете, и сейчас установил интервал между 2018-2022 годами. Затем я использовал это для обновления таблицы, и все рассчитанные даты с использованием номера недели и дня были заполнены. Вы действительно мне помогли. Удачной недели / жизни
Это прекрасно работает. Спасибо. Мне трудно понять, как я бы использовал это для обновления другой таблицы с пустым полем CalcDate, используя поля weekno и dayno, которые находятся в той же строке.