programing

SQL Server에서 주의 첫 번째 요일 가져오기

jooyons 2023. 5. 25. 21:59
반응형

SQL Server에서 주의 첫 번째 요일 가져오기

집계된 날짜를 주 1일로 저장하여 기록을 주별로 그룹화하려고 합니다.그러나 날짜 반올림에 사용하는 표준 기술이 몇 주 동안 제대로 작동하지 않는 것 같습니다(몇 일, 몇 달, 몇 년, 분기 및 적용한 다른 기간에도 작동함).

SQL은 다음과 같습니다.

select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);

은 니다됩반을 반환합니다.2011-08-22 00:00:00.000일요일이 아니라 월요일입니다.의 선택@@datefirst아온다를 합니다.7일요일의 코드이기 때문에 서버가 올바르게 설정되어 있는 것으로 알고 있습니다.

위의 코드를 다음으로 변경하면 충분히 쉽게 우회할 수 있습니다.

select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), -1);

하지만 그런 예외를 만들어야 한다는 사실이 저를 조금 불안하게 만듭니다.또한 중복된 질문이라면 사과드립니다.저는 몇 가지 관련 질문을 찾았지만 이 측면을 구체적으로 다룬 질문은 없었습니다.

일요일이 아닌 월요일을 받는 이유에 대해 답변하기

날짜 0에 몇 주를 추가하고 있습니다.0은 입니까? 0은 언제입니까? 1900-01-01입니다.1900-01-01일이 무슨 요일이었습니까?1월부터 몇 주가 그래서 당신의 코드에서 1900년 1월 1일 월요일 이후로 몇 주가 지났습니까?그걸 [n]이라고 하죠. [1일합니다.1900년 1월 1일 월요일에 [n]주를 추가합니다.당신은 이것이 월요일로 끝나는 것에 놀라지 말아야 합니다. DATEADD를 들어 당이 몇주추싶일만전모일르, 일일때만지까도에할요, 착단그것은고추마것지 7치다을더가는입니하그 7음추에다하신을가지고혀를가하지은▁like▁has일▁......치s마▁just▁just일▁but,'▁adding다▁it▁days▁only▁that▁want▁until▁you▁no▁weeks...DATEDIFF교차된 경계만 인식합니다.예를 들어, 일부 사람들이 일부 합리적인 논리가 포함되어 있어야 한다고 불평하더라도, 이 둘은 모두 1을 반환합니다.

SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');

일요일을 얻는 방법에 대한 답변:

일요일을 원하는 경우 월요일이 아닌 일요일 기준 날짜를 선택합니다.예:

DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);

이것은 당신이 당신의 것을 바꾸어도 깨지지 않을 것입니다.DATEFIRST설정(또는 코드가 다른 설정을 가진 사용자에 대해 실행 중임) - 현재 설정과 상관없이 일요일을 원하는 경우.만약 당신이 그 두 개의 답을 jive로 하고 싶다면, 당신은 다음에 의존하는 함수를 사용해야 합니다.DATEFIRST 예:

SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);

그래서 만약 당신이 당신의 것을 바꾼다면.DATEFIRST월요일, 화요일로 설정하면 동작이 변경됩니다.원하는 동작에 따라 다음 기능 중 하나를 사용할 수 있습니다.

CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
    @d DATE
)
RETURNS DATE
AS
BEGIN
    RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO

...아니면...

CREATE FUNCTION dbo.StartOfWeek2 -- always the DATEFIRST weekday
(
    @d DATE
)
RETURNS DATE
AS
BEGIN
    RETURN (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, @d), @d));
END
GO

이제 대안이 많이 있지만, 어떤 것이 가장 잘 수행됩니까?큰 차이가 있다면 놀라겠지만, 저는 지금까지 제공된 모든 답을 모아서 저렴한 것과 비싼 것 두 가지 테스트를 통해 테스트를 진행했습니다.I/O 또는 메모리가 성능에 영향을 미치지 않기 때문에 클라이언트 통계를 측정했습니다(기능이 사용되는 방식에 따라 작동할 수도 있음).검사 결과는 다음과 같습니다.

"저렴한" 할당 쿼리:

Function - client processing time / wait time on server replies / total exec time
Gandarez     - 330/2029/2359 - 0:23.6
me datefirst - 329/2123/2452 - 0:24.5
me Sunday    - 357/2158/2515 - 0:25.2
trailmax     - 364/2160/2524 - 0:25.2
Curt         - 424/2202/2626 - 0:26.3

"비싼" 할당 쿼리:

Function - client processing time / wait time on server replies / total exec time
Curt         - 1003/134158/135054 - 2:15
Gandarez     -  957/142919/143876 - 2:24
me Sunday    -  932/166817/165885 - 2:47
me datefirst -  939/171698/172637 - 2:53
trailmax     -  958/173174/174132 - 2:54

저는 제 시험에 대한 세부 사항을 원할 경우 전달할 수 있습니다. 이미 상당히 긴 시간이 흐르고 있기 때문에 여기서 멈출 수 있습니다.계산 횟수와 인라인 코드를 고려할 때 커트의 것이 하이엔드에서 가장 빠르게 나오는 것을 보고 조금 놀랐습니다.좀 더 철저한 테스트를 해보고 블로그에 글을 올려볼까 합니다.제가 당신들의 기능을 다른 곳에 게시하는 것에 반대하지 않는다면요.

다음을 수행해야 하는 경우:

월요일 = 1 및 일요일 = 7:

SELECT 1 + ((5 + DATEPART(dw, GETDATE()) + @@DATEFIRST) % 7);

일요일 = 1 및 토요일 = 7:

SELECT 1 + ((6 + DATEPART(dw, GETDATE()) + @@DATEFIRST) % 7);

위에도 비슷한 예가 있었지만, "%7" 두 배 덕분에 훨씬 느릴 것입니다.

DBA가 작업 중에 답변이 필요하고 기능을 생성하는 것을 금지하는 경우 다음 솔루션이 효과적입니다.

select *,
cast(DATEADD(day, -1*(DATEPART(WEEKDAY, YouDate)-1), YourDate) as DATE) as WeekStart
From.....

이것이 그 주의 시작을 알려줍니다.여기서 저는 일요일이 몇 주의 시작이라고 가정합니다.월요일이 시작이라고 생각하는 경우 다음을 사용해야 합니다.

select *,
cast(DATEADD(day, -1*(DATEPART(WEEKDAY, YouDate)-2), YourDate) as DATE) as WeekStart
From.....

이것은 저에게 매우 유용합니다.

CREATE FUNCTION [dbo].[주 시작](@입력 날짜 날짜 시간)날짜/시간 반환
~하듯이시작한다.이 기능은 작동하지 않습니다.
SET DATE FIRST 1 - 월요일을 주의 첫 번째 요일로 설정합니다.

@DOW INT 선언 - 요일을 저장합니다.SET @입력 날짜 = 변환(VARCHAR(10), @입력 날짜, 111)설정 @DOW = DATE 파트(DW, @INPUTDATE)
월요일을 1로, 화요일을 2로 마법 변환하는 등.나는 한 주의 시작에 대해 SQL 서버가 생각하는 것을 존중합니다.
하지만 여기서는 일요일이 0으로 표시되어 있지만 나중에 수정합니다.
SET @DOW = (@DOW + @DATEFIRST - 1) %7IF @DOW = 0 SET @DOW = 7 -- 일요일에 대한 수정
반환 날짜 추가(DD, 1 - @DOW, @INPUT DATE)
끝.

이게 필요할 수도 있습니다.

SELECT DATEADD(DD, 1 - DATEPART(DW, GETDATE()), GETDATE())

또는

DECLARE @MYDATE DATETIME
SET @MYDATE = '2011-08-23'
SELECT DATEADD(DD, 1 - DATEPART(DW, @MYDATE), @MYDATE)

기능.

CREATE FUNCTION [dbo].[GetFirstDayOfWeek]
( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN

SET @pInputDate = CONVERT(VARCHAR(10), @pInputDate, 111)
RETURN DATEADD(DD, 1 - DATEPART(DW, @pInputDate),
               @pInputDate)

END
GO

다음 스크립트를 검색했습니다.

create function dbo.F_START_OF_WEEK
(
    @DATE           datetime,
    -- Sun = 1, Mon = 2, Tue = 3, Wed = 4
    -- Thu = 5, Fri = 6, Sat = 7
    -- Default to Sunday
    @WEEK_START_DAY     int = 1 
)
/*
Find the fisrt date on or before @DATE that matches 
day of week of @WEEK_START_DAY.
*/
returns     datetime
as
begin
declare  @START_OF_WEEK_DATE    datetime
declare  @FIRST_BOW     datetime

-- Check for valid day of week
if @WEEK_START_DAY between 1 and 7
    begin
    -- Find first day on or after 1753/1/1 (-53690)
    -- matching day of week of @WEEK_START_DAY
    -- 1753/1/1 is earliest possible SQL Server date.
    select @FIRST_BOW = convert(datetime,-53690+((@WEEK_START_DAY+5)%7))
    -- Verify beginning of week not before 1753/1/1
    if @DATE >= @FIRST_BOW
        begin
        select @START_OF_WEEK_DATE = 
        dateadd(dd,(datediff(dd,@FIRST_BOW,@DATE)/7)*7,@FIRST_BOW)
        end
    end

return @START_OF_WEEK_DATE

end
go

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307

FUNCTION dbo.fn 일주일 중 첫 근무일 생성(@current날짜)반품 INT~하듯이시작한다.DATE FIRST 설정 가져오기@dsint = @@DATEFIRST 선언현재 DATEFIRST 설정에서 요일 번호 가져오기DELECT @detail int = DATEPART(dw,@currentDate)
DELECT @wdint = 1+((@dir+@ds) % 7 -- 항상 월요일을 1로, 화요일을 2로 반환합니다...태양을 7로
반품 날짜 추가(dd,1-@wd,@currentDate)
끝.

기본(현재 주의 일요일)의 경우

select cast(dateadd(day,-(datepart(dw,getdate())-1),getdate()) as date)

이전 주의 경우:

select cast(dateadd(day,-(datepart(dw,getdate())-1),getdate()) -7 as date)

내부적으로 우리는 그것을 하는 기능을 만들었지만, 만약 당신이 빠르고 더러운 것이 필요하다면, 이것은 그것을 할 것입니다.

Julian date 0은 월요일이므로 -1 전날인 일요일에 주 수를 추가하면 됩니다. date add(wk, datediff(wk,0,getdate()),-1을 선택합니다.

저는 당신이 월요일을 한 주의 시작으로 원하신다면 다른 답변들이 장황하거나 실제로 효과가 없다는 것을 발견했습니다.

일요일.

SELECT DATEADD(week, DATEDIFF(week, -1, GETDATE()), -1) AS Sunday;

월요일.

SELECT DATEADD(week, DATEDIFF(week, 0, GETDATE() - 1), 0) AS Monday;
Set DateFirst 1;

Select 
    Datepart(wk, TimeByDay) [Week]
    ,Dateadd(d,
                CASE 
                WHEN  Datepart(dw, TimeByDay) = 1 then 0
                WHEN  Datepart(dw, TimeByDay) = 2 then -1
                WHEN  Datepart(dw, TimeByDay) = 3 then -2
                WHEN  Datepart(dw, TimeByDay) = 4 then -3
                WHEN  Datepart(dw, TimeByDay) = 5 then -4
                WHEN  Datepart(dw, TimeByDay) = 6 then -5
                WHEN  Datepart(dw, TimeByDay) = 7 then -6
                END
                , TimeByDay) as StartOfWeek

from TimeByDay_Tbl

이것이 제 논리입니다.주의 첫 번째를 월요일로 설정하고 지정된 요일을 계산한 다음 DateAdd 및 Case를 사용하여 해당 주의 이전 월요일에 해당 날짜가 있었을 것으로 계산합니다.

이것은 나에게 유용한 기능입니다.

/* MeRrais 211126 
select [dbo].[SinceWeeks](0,NULL)
select [dbo].[SinceWeeks](5,'2021-08-31')
*/
alter Function [dbo].[SinceWeeks](@Weeks int, @From datetime=NULL)
Returns date
AS
Begin   

    if @From is null 
        set @From=getdate()

    return cast(dateadd(day, -(@Weeks*7+datepart(dw,@From)-1), @From) as date)
END

여기에 제시된 답변에는 문제가 없지만, 제 답변은 구현과 이해가 훨씬 더 간단하다고 생각합니다.성능 테스트를 해본 적은 없지만 무시해도 될 것 같습니다.

그래서 SQL Server에 날짜가 정수로 저장되어 있다는 사실에서 답을 얻었습니다. (날짜 구성 요소만 말하는 것입니다.)만약 당신이 나를 믿지 않는다면, 이 SELECT CONVERT(INT, GETDATE())를 사용해 보세요.

이제 이것을 알면, 여러분은 멋진 수학 방정식을 만들 수 있습니다.당신은 더 좋은 것을 생각해 낼 수 있을지도 모르지만, 여기 제 것이 있습니다.

/*
TAKEN FROM http://msdn.microsoft.com/en-us/library/ms181598.aspx
First day of the week is
1 -- Monday
2 -- Tuesday
3 -- Wednesday
4 -- Thursday
5 -- Friday
6 -- Saturday
7 (default, U.S. English) -- Sunday
*/

--Offset is required to compensate for the fact that my @@DATEFIRST setting is 7, the default. 
DECLARE @offSet int, @testDate datetime
SELECT @offSet = 1, @testDate = GETDATE()

SELECT CONVERT(DATETIME, CONVERT(INT, @testDate) - (DATEPART(WEEKDAY, @testDate) - @offSet))

저도 비슷한 문제가 있었습니다.날짜가 주어진다면, 저는 그 주 월요일의 날짜를 받고 싶었습니다.

저는 다음과 같은 논리를 사용했습니다.요일 번호를 0-6 범위에서 찾은 다음 원래 날짜에서 빼십시오.

사용하였습니다: DATEADD(day,-(DATEPART(weekday,)+5)%7,)

DATEPRRT(weekday,)가 1 = Sundaye를 반환하므로...7=토요일, DATEPART(평일,)+5)%7 반환 0=취소...6=일요일.

원래 날짜에서 이 일수를 빼면 이전 월요일이 표시됩니다.동일한 기법을 주의 모든 시작 요일에 사용할 수 있습니다.

저는 이것이 간단하고 유용하다는 것을 알았습니다.첫 번째 요일이 일요일이나 월요일이라도 작동합니다.

@기준일을 날짜로 선언

SET @BaseDate = GETDATE()

@FirstDow를 날짜로 선언

@First DOWN = DATEADD(d,DATEPART(WEEKDAY,@BaseDate) *-1 + 1, @BaseDate)를 선택합니다.

제가 여기서 너무 단순화한 것일 수도 있고, 그럴 수도 있지만, 이것은 저에게 효과가 있는 것 같습니다.아직 문제가 생긴 적은 없습니다

CAST('1/1/' + CAST(YEAR(GETDATE()) AS VARCHAR(30)) AS DATETIME) + (DATEPART(wk, YOUR_DATE) * 7 - 7) as 'FirstDayOfWeek'
CAST('1/1/' + CAST(YEAR(GETDATE()) AS VARCHAR(30)) AS DATETIME) + (DATEPART(wk, YOUR_DATE) * 7) as 'LastDayOfWeek'

언급URL : https://stackoverflow.com/questions/7168874/get-first-day-of-week-in-sql-server

반응형