Получение номера недели от даты в MS SQL Server 2005?

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

Есть идеи? Также, откуда я родом, неделя начинается в понедельник, а неделя 1 - это первая неделя года, по крайней мере, с 4 днями.

Связанный:

How do I calculate the week number given a date?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
65 514
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Похоже, DATEPART функция mssql должен помочь вам с ...

DATEPART(wk, ‘Jan 1, xxxx’) = 1

Хорошо, я буду .. оказывается, есть способ установить первый день недели, ДАТА ПЕРВАЯ

SET DATEFIRST 1 -- for monday

Обновлять: Теперь я лучше понимаю, чего хочет OP ... что является настраиваемой логикой для этого. Я не думаю, что у MSSQL были бы функции с таким богатым уровнем настройки. Но я могу ошибаться ... Думаю, вам придется сюда свернуть свой UDF ... извините

Нет, Hojou ищет номер недели ISO (ISO 8601). Это должно быть решено с помощью UDF.

Jonas Lincoln 08.12.2008 11:50

Это вернет вам номер недели даты, введенной в кавычки.

SELECT DATEPART( wk, 'enter the date over here' )

Это не гарантирует стандарт ISO 8601, как указано в вопросе.

Ian 12.08.2016 12:16

Похоже, что 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;)

Per Hornshøj-Schierbeck 08.12.2008 12:09

Но если вы проверите, делает ли это UDF - это будет быстрее, чем дополнительная таблица (если это важно для вас), и вам также не придется читать ее очень часто. ;-) Как я уже сказал, есть и другие реализации, если вам не нравится / нельзя использовать эту.

Tomalak 08.12.2008 12:14

Я бы подумал, что вызов этого udf займет больше времени, чем соединение в индексированной таблице даты / недели? Я могу ошибаться, но сфокусируйтесь на этой задаче, чтобы упростить задачу на низком уровне (все знают, как выполнить внутреннее соединение, но не все поймут этот udf). Спасибо, что подняли этот вопрос - возможно, мне придется его протестировать;)

Per Hornshøj-Schierbeck 08.12.2008 15:04

Поскольку UDF просто выполняет базовую математику без ввода-вывода вообще, это будет быстрее, чем любое соединение. И вызвать / использовать его так же просто, как вызвать обычную функцию («SELECT dbo.ISOweek (MyDateTime)»), вы даже можете добавить ее в главную БД, чтобы она была доступна на всем сервере.

Tomalak 08.12.2008 16:17

Это очень длинный синтаксис, логику можно записать всего в 2 строки

t-clausen.dk 02.09.2011 20:23

Tomalak Я сделал, однако я не собираюсь публиковать его по вопросу, которому 3 года

t-clausen.dk 04.09.2011 01:29

@ tclausen.dk Тогда почему ты не стал комментировать?

Tomalak 04.09.2011 01:51

Это может показаться глупым, но я видел много статей об этом, и ВСЕ они были спагетти-кодом. Так что я подумываю о том, чтобы пойти на значок самоучителя и / или написать об этом статью. Если я опубликую решение по вопросу трехлетней давности, в моей статье не будет ничего нового, и ответ уйдет в небытие, и я не получу никакого признания (я уже пробовал это, отвечая на вопрос годичной давности с 0 ответами ).

t-clausen.dk 04.09.2011 10:13

Разместил этот вопрос и ответ stackoverflow.com/questions/7330711/isoweek-in-sql-server-20‌ 05

t-clausen.dk 07.09.2011 18:12

Вы когда-нибудь слышали о DATEPART (ISO_WEEK, @ DATE)?

Stefan Steiger 20.09.2011 13:12

@Quandary да, но у sql-server 2005 нет

t-clausen.dk 03.05.2013 13:19

Я пробовал это, и он НЕ рассчитал правильные номера недель ISO. Это делает: RETURN (datepart (DY, dateiff (d, 0, @DATE) / 7 * 7 + 3) +6) / 7

Ian 09.12.2015 13:20

@Kleky Твоя вина. Вы просто скопировали код и не прочитали текст в ответе.

Tomalak 09.12.2015 14:25

Ну, функция либо возвращает номер недели ISO, либо нет - давайте не будем загадывать это

Ian 09.12.2015 15:55

@Kleky Вы все еще не прочитали текст моего ответа. Иди, прочитай это сейчас. Дело не в том, чтобы быть загадочным, но если вы критикуете меня, сделайте это за ошибку, которую я совершил.

Tomalak 09.12.2015 19:43

Вам нужна неделя 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

Спасибо, это просто понадобилось сегодня. Это более правильный ответ, чем принятый ответ.

dverespey 22.10.2009 22:58

Вы когда-нибудь слышали о DATEPART (ISO_WEEK, @ DATE)?

Stefan Steiger 20.09.2011 13:13

@Quandary Он искал решение для SQL Server 2005, которое не поддерживает ISO_WEEK.

Jonas Lincoln 21.09.2011 10:52

Для меня это дало лучший результат, чем ответ Томалака - на 28 сентября 2014 года он возвращает 39 (и это правильно! - weeknumber.net/?q=2014-09-28), а ответ Томалака возвращает 40.

sarh 26.09.2014 17:43

Вы рассматривали возможность использования функции 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:

  • WeekNumber: 50
  • FirstWeekOfYear: 1
  • LastWeekOfYear: 53

Надеюсь, это поможет :)

Похоже, у него такая же проблема с DatePart (wk, getdate ()), и он не будет работать. SELECT {fn WEEK ('2003-12-31')} AS WeekNumber дает мне 53, что неверно, поскольку правильный номер недели - 1

Per Hornshøj-Schierbeck 08.12.2008 14:59

ЗАБУДЬТЕ ДРУГИЕ ОТВЕТЫ

В вопросе указано «неделя начинается в понедельник, а неделя 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, как указано в вопросе.

Ian 12.08.2016 12:16

но, по крайней мере, это отправная точка, и они могут играть со своими собственными настройками Культуры.

Fandango68 14.08.2016 02:02

@Kleky, неверно. OP ничего не упомянул о стандарте ISO

Fandango68 14.08.2016 02:03

«Кроме того, там, где я родом, неделя начинается в понедельник, а неделя 1 - это первая неделя года, состоящая как минимум из 4 дней». = Стандарт ISO

Ian 14.08.2016 10:35

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