Можно ли создать оператор sql, который выбирает номер недели (НЕ день недели - или номер дня в неделе). Я создаю представление, чтобы выбрать эту дополнительную информацию вместе с парой других полей и, следовательно, не могу использовать хранимую процедуру. Я знаю, что для этого можно создать UDF, но если это вообще возможно, мне лучше добавить только представление в эту базу данных, чем представление и функцию.
Есть идеи? Также, откуда я родом, неделя начинается в понедельник, а неделя 1 - это первая неделя года, по крайней мере, с 4 днями.





Похоже, DATEPART функция mssql должен помочь вам с ...
DATEPART(wk, ‘Jan 1, xxxx’) = 1
Хорошо, я буду .. оказывается, есть способ установить первый день недели, ДАТА ПЕРВАЯ
SET DATEFIRST 1 -- for monday
Обновлять: Теперь я лучше понимаю, чего хочет OP ... что является настраиваемой логикой для этого. Я не думаю, что у MSSQL были бы функции с таким богатым уровнем настройки. Но я могу ошибаться ... Думаю, вам придется сюда свернуть свой UDF ... извините
Это вернет вам номер недели даты, введенной в кавычки.
SELECT DATEPART( wk, 'enter the date over here' )
Это не гарантирует стандарт ISO 8601, как указано в вопросе.
Похоже, что datepart поможет вам в этом, но вам придется отрегулировать, чтобы получить правильный номер недели, исходя из дня недели 1 января данного года. Я недостаточно знаком с T-SQL, чтобы сделать это, но это должно быть возможно. Жаль, что нет аргумента режима, как в MySQL
Имейте в виду, что есть различия в том, что считается правильным номером недели, в зависимости от культуры. Номера недель зависят от нескольких предположений, которые различаются от страны к стране, см. Статья в Википедии по этому поводу. К номерам недель применяется Стандарт ISO (ISO 8601).
Функция DATEPART(), встроенная в SQL-сервер, не обязательно работает как надо. SQL Server предполагает, что первым днем недели 1 будет 1 января, для многих приложений это неверно.
Правильное вычисление номеров недель нетривиально, и в Интернете можно найти различные реализации. Например, есть UDF, которая вычисляет Номера недель ISO с 1930-2030 гг., являясь одной из многих других. Вам нужно будет проверить, что вам подходит.
Это от Книги в Интернете (хотя вы, вероятно, захотите использовать тот из ответа Джонаса Линкольна, версия BOL кажется неправильной):
CREATE FUNCTION ISOweek (@DATE DATETIME)
RETURNS INT
AS
BEGIN
DECLARE @ISOweek INT
SET @ISOweek = DATEPART(wk,@DATE)
+1
-DATEPART(wk,CAST(DATEPART(yy,@DATE) AS CHAR(4))+'0104')
-- Special cases: Jan 1-3 may belong to the previous year
IF (@ISOweek=0)
SET @ISOweek = dbo.ISOweek(CAST(DATEPART(yy,@DATE) - 1
AS CHAR(4))+'12'+ CAST(24+DATEPART(DAY,@DATE) AS CHAR(2)))+1
-- Special case: Dec 29-31 may belong to the next year
IF ((DATEPART(mm,@DATE)=12) AND
((DATEPART(dd,@DATE)-DATEPART(dw,@DATE))>= 28))
SET @ISOweek=1
RETURN(@ISOweek)
END
GO
Спасибо - мне нравится явная информация о номерах недель, помимо UDF - я думаю, что решу эту проблему, создав таблицу с номерами недель (или первым днем недели 1), с которыми я могу выполнить простую логику, на мой взгляд. Плохая часть - это дополнительная таблица, но я думаю, что она лучше трудночитаемой UDF;)
Но если вы проверите, делает ли это UDF - это будет быстрее, чем дополнительная таблица (если это важно для вас), и вам также не придется читать ее очень часто. ;-) Как я уже сказал, есть и другие реализации, если вам не нравится / нельзя использовать эту.
Я бы подумал, что вызов этого udf займет больше времени, чем соединение в индексированной таблице даты / недели? Я могу ошибаться, но сфокусируйтесь на этой задаче, чтобы упростить задачу на низком уровне (все знают, как выполнить внутреннее соединение, но не все поймут этот udf). Спасибо, что подняли этот вопрос - возможно, мне придется его протестировать;)
Поскольку UDF просто выполняет базовую математику без ввода-вывода вообще, это будет быстрее, чем любое соединение. И вызвать / использовать его так же просто, как вызвать обычную функцию («SELECT dbo.ISOweek (MyDateTime)»), вы даже можете добавить ее в главную БД, чтобы она была доступна на всем сервере.
Это очень длинный синтаксис, логику можно записать всего в 2 строки
Tomalak Я сделал, однако я не собираюсь публиковать его по вопросу, которому 3 года
@ tclausen.dk Тогда почему ты не стал комментировать?
Это может показаться глупым, но я видел много статей об этом, и ВСЕ они были спагетти-кодом. Так что я подумываю о том, чтобы пойти на значок самоучителя и / или написать об этом статью. Если я опубликую решение по вопросу трехлетней давности, в моей статье не будет ничего нового, и ответ уйдет в небытие, и я не получу никакого признания (я уже пробовал это, отвечая на вопрос годичной давности с 0 ответами ).
Разместил этот вопрос и ответ stackoverflow.com/questions/7330711/isoweek-in-sql-server-20 05
Вы когда-нибудь слышали о DATEPART (ISO_WEEK, @ DATE)?
@Quandary да, но у sql-server 2005 нет
Я пробовал это, и он НЕ рассчитал правильные номера недель ISO. Это делает: RETURN (datepart (DY, dateiff (d, 0, @DATE) / 7 * 7 + 3) +6) / 7
@Kleky Твоя вина. Вы просто скопировали код и не прочитали текст в ответе.
Ну, функция либо возвращает номер недели ISO, либо нет - давайте не будем загадывать это
@Kleky Вы все еще не прочитали текст моего ответа. Иди, прочитай это сейчас. Дело не в том, чтобы быть загадочным, но если вы критикуете меня, сделайте это за ошибку, которую я совершил.
Вам нужна неделя ISO. Вот реализация из http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510:
drop function dbo.F_ISO_WEEK_OF_YEAR
go
create function dbo.F_ISO_WEEK_OF_YEAR
(
@Date datetime
)
returns int
as
/*
Function F_ISO_WEEK_OF_YEAR returns the
ISO 8601 week of the year for the date passed.
*/
begin
declare @WeekOfYear int
select
-- Compute week of year as (days since start of year/7)+1
-- Division by 7 gives whole weeks since start of year.
-- Adding 1 starts week number at 1, instead of zero.
@WeekOfYear =
(datediff(dd,
-- Case finds start of year
case
when NextYrStart <= @date
then NextYrStart
when CurrYrStart <= @date
then CurrYrStart
else PriorYrStart
end,@date)/7)+1
from
(
select
-- First day of first week of prior year
PriorYrStart =
dateadd(dd,(datediff(dd,-53690,dateadd(yy,-1,aa.Jan4))/7)*7,-53690),
-- First day of first week of current year
CurrYrStart =
dateadd(dd,(datediff(dd,-53690,aa.Jan4)/7)*7,-53690),
-- First day of first week of next year
NextYrStart =
dateadd(dd,(datediff(dd,-53690,dateadd(yy,1,aa.Jan4))/7)*7,-53690)
from
(
select
--Find Jan 4 for the year of the input date
Jan4 =
dateadd(dd,3,dateadd(yy,datediff(yy,0,@date),0))
) aa
) a
return @WeekOfYear
end
go
Спасибо, это просто понадобилось сегодня. Это более правильный ответ, чем принятый ответ.
Вы когда-нибудь слышали о DATEPART (ISO_WEEK, @ DATE)?
@Quandary Он искал решение для SQL Server 2005, которое не поддерживает ISO_WEEK.
Для меня это дало лучший результат, чем ответ Томалака - на 28 сентября 2014 года он возвращает 39 (и это правильно! - weeknumber.net/?q=2014-09-28), а ответ Томалака возвращает 40.
Вы рассматривали возможность использования функции WEEK?
Это даст вам неделю в году для указанной даты, в которую вы перейдете.
SELECT { fn WEEK(GETDATE()) } AS WeekNumber, { fn WEEK(CONVERT(DATETIME, '2008-01-01 00:00:00', 102)) } AS FirstWeekOfYear, { fn WEEK(CONVERT(DATETIME, '2008-12-31 00:00:00', 102)) } AS LastWeekOfYear
Это выводит следующие SQL2000 и SQL2005:
Надеюсь, это поможет :)
Похоже, у него такая же проблема с DatePart (wk, getdate ()), и он не будет работать. SELECT {fn WEEK ('2003-12-31')} AS WeekNumber дает мне 53, что неверно, поскольку правильный номер недели - 1
ЗАБУДЬТЕ ДРУГИЕ ОТВЕТЫ
В вопросе указано «неделя начинается в понедельник, а неделя 1 - это первая неделя года, состоящая как минимум из 4 дней.». Это Стандарт ISO 8601 и что дает этот ответ. Эта функция используется в продакшене на нашем сайте.
Это все, что вам нужно:
CREATE FUNCTION ISOweek (@DATE DATETIME)
RETURNS INT
AS
BEGIN
RETURN (datepart(DY, datediff(d, 0, @DATE) / 7 * 7 + 3)+6) / 7
END
GO
Меня удивляет, почему опять люди делают горы из кротовых холмов?
Так просто...
select DATEPART(wk, GETDATE())
Это не гарантирует стандарт ISO 8601, как указано в вопросе.
но, по крайней мере, это отправная точка, и они могут играть со своими собственными настройками Культуры.
@Kleky, неверно. OP ничего не упомянул о стандарте ISO
«Кроме того, там, где я родом, неделя начинается в понедельник, а неделя 1 - это первая неделя года, состоящая как минимум из 4 дней». = Стандарт ISO
Нет, Hojou ищет номер недели ISO (ISO 8601). Это должно быть решено с помощью UDF.