Установка значения поля даты SQL на основе поля номера недели и номера дня

Есть ли процедура или средство для установки значения даты на основе значения недели и дня.

Для дальнейшего использования этого календарного года: 1-7 января - первая неделя, 8-14 января - вторая неделя и т. д.

Что касается значения числа дней; Понедельник 1 Вторник 2 Среда 3 Четверг 4 Пятница 5.

Используя эту логику, я хочу создать и заполнить поле даты, которое использует эти значения.

Например, я хочу, чтобы Неделя: 2 - День: 3 заполняла мое новое поле даты как 01.10.2018.

Будем очень признательны за любую помощь и руководство.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
0
477
3

Ответы 3

Вы можете сослаться на эту ссылку, в которой есть инструкция по созданию календарной таблицы. 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;

Это прекрасно работает. Спасибо. Мне трудно понять, как я бы использовал это для обновления другой таблицы с пустым полем CalcDate, используя поля weekno и dayno, которые находятся в той же строке.

potatochucker 02.11.2018 16:46

@potatochucker Просто посмотрите, как нормально обновлять таблицу, и воспользуйтесь расчетом. Как в: update yourtable set yourfield = <put calculation here> where yourfield is null. Но если это для одноразового обновления, я бы жестко запрограммировал год вместо того, чтобы рассчитывать его из GetDate.

LukStorms 02.11.2018 17:03

@potatochucker Я немного изменил расчет.

LukStorms 02.11.2018 23:46

Спасибо за понимание и помощь. Я реализовал ваш код и протестировал его со своей стороны, но у меня есть проблема, когда мне нужно, чтобы это выходило за рамки одного года. У меня есть поле, в котором записывается значение года «2018», «2019» и т. д. Может ли это использоваться как средство установки общей даты без необходимости объявлять каждый данный год и вставлять его в tmpDates? Или есть способ вставить несколько лет в даты tmp? Спасибо еще раз!

potatochucker 05.11.2018 14:41

@potatochucker Вам следует внимательно изучить второе решение в таблице. Вы можете установить переменные для startDate и endDate, а затем просто использовать их в SQL для #tmpDates. И переименуйте DATE2018 CTE в DATES. (потому что это звучит неправильно для дат с 2017 года; p) И установите MAXRECURSION выше или равным 0. На самом деле, вместо # временной таблицы ее можно было бы сделать постоянной таблицей с дополнительными полями, связанными с датой. Чтобы сделать его многоразовым для других запросов, обычно называется Calendar.

LukStorms 05.11.2018 14:50

Теперь все работает отлично. Я сделал календарную таблицу, как вы предлагаете, и сейчас установил интервал между 2018-2022 годами. Затем я использовал это для обновления таблицы, и все рассчитанные даты с использованием номера недели и дня были заполнены. Вы действительно мне помогли. Удачной недели / жизни

potatochucker 05.11.2018 16:10

Другие вопросы по теме