Programing

SQL Server에서 요일 가져 오기

lottogame 2020. 9. 9. 20:08
반응형

SQL Server에서 요일 가져 오기


집계 된 날짜를 요일로 저장하여 레코드를 주별로 그룹화하려고합니다. 그러나 날짜를 반올림하는 데 사용하는 표준 기술은 주 단위로 올바르게 작동하지 않는 것 같습니다 (일, 월, 년, 분기 및 내가 적용한 다른 기간에는 작동하지만).

다음은 SQL입니다.

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

이것은 2011-08-22 00:00:00.000일요일이 아니라 월요일을 반환합니다 . 일요일의 코드 인 @@datefirstreturns를 선택하면 7내가 아는 한 서버가 올바르게 설정됩니다.

위의 코드를 다음과 같이 변경하여 쉽게 우회 할 수 있습니다.

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

하지만 그런 예외를 만들어야한다는 사실이 조금 불안해합니다. 또한 중복 질문 인 경우 사과드립니다. 몇 가지 관련 질문을 찾았지만이 측면을 구체적으로 다루는 질문은 없습니다.


일요일이 아닌 월요일을받는 이유에 대한 답변 :

날짜 0에 몇 주를 추가합니다. 날짜 0이 무엇입니까? 1900-01-01. 1900-01-01의 날은 어땠습니까? 월요일. 그래서 여러분의 코드에서 1900 년 1 월 1 일 월요일 이후 몇 주가 지났습니까? 그것을 [n]이라고 부릅시다. 좋습니다. 이제 1900 년 1 월 1 일 월요일에 [n] 주를 추가하십시오. 이것이 월요일이된다는 사실에 놀라지 마십시오. DATEADD주를 추가하고 싶다는 생각은 없지만 일요일이 될 때까지만 7 일을 더한 다음 7 일을 더 추가 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현재 설정에 관계없이 여전히 일요일을 원하면 설정 을 변경 하거나 코드가 다른 설정을 가진 사용자를 위해 실행되는 경우에도 중단되지 않습니다 . 당신이 흔들로 두 답변을 원하는 경우에, 당신은 함수 사용해야 않는 에 따라 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

원하는 경우 테스트 세부 정보를 전달할 수 있습니다. 이미 상당히 긴 시간이 소요되고 있으므로 여기서 중지합니다. 계산과 인라인 코드의 수를 감안할 때 Curt가 최고급에서 가장 빠르게 나오는 것을보고 약간 놀랐습니다. 아마도 좀 더 철저한 테스트를 실행하고 그것에 대해 블로그를 할 것입니다. 만약 여러분이 다른 곳에 여러분의 함수를 게시하는 것에 반대하지 않는다면.


필요한 항목 :

월요일 = 1, 일요일 = 7 :

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

일요일 = 1, 토요일 = 7 :

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

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


이것은 나를 위해 훌륭하게 작동합니다.

CREATE FUNCTION [dbo]. [StartOfWeek]
(
  @INPUTDATE DATETIME
)
DATETIME 반환

같이
시작
  -이 기능은 작동하지 않습니다.
  -SET DATEFIRST 1-월요일을 요일로 설정합니다.

  DECLARE @DOW INT-요일 저장
  SET @INPUTDATE = CONVERT (VARCHAR (10), @INPUTDATE, 111)
  SET @DOW = DATEPART (DW, @INPUTDATE)

  -월요일을 1로, 화요일을 2로 매직 변환
  -SQL 서버가 한주의 시작에 대해 어떻게 생각하는지에 관계없이.
  -하지만 여기서는 일요일이 0으로 표시되어 있지만 나중에 수정합니다.
  SET @DOW = (@DOW + @@ DATEFIRST-1) % 7
  @DOW = 0 SET @DOW = 7이면 일요일 수정

  반환 날짜 ADD (DD, 1-@ DOW, @ INPUTDATE)

종료

직장에서 답변이 필요하고 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.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


아마도 이것이 필요할 것입니다.

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

함수 생성 dbo.fnFirstWorkingDayOfTheWeek
(
    @currentDate 날짜
)
INT 반환
AS
BEGIN
    -- get DATEFIRST setting
    DECLARE @ds int = @@DATEFIRST 
    -- get week day number under current DATEFIRST setting
    DECLARE @dow int = DATEPART(dw,@currentDate) 

    DECLARE @wd  int =  1+(((@dow+@ds) % 7)+5) % 7  -- this is always return Mon as 1,Tue as 2 ... Sun as 7 

    RETURN DATEADD(dd,1-@wd,@currentDate) 

END

For the basic (the current week's Sunday)

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

If previous week:

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

Internally, we built a function that does it but if you need quick and dirty, this will do it.


Since Julian date 0 is a Monday just add the number of weeks to Sunday which is the day before -1 Eg. select dateadd(wk,datediff(wk,0,getdate()),-1)


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

This is my logic. Set the first of the week to be Monday then calculate what is the day of the week a give day is, then using DateAdd and Case I calculate what the date would have been on the previous Monday of that week.


I don't have any issues with any of the answers given here, however I do think mine is a lot simpler to implement, and understand. I have not run any performance tests on it, but it should be neglegable.

So I derived my answer from the fact that dates are stored in SQL server as integers, (I am talking about the date component only). If you don't believe me, try this SELECT CONVERT(INT, GETDATE()), and vice versa.

Now knowing this, you can do some cool math equations. You might be able to come up with a better one, but here is mine.

/*
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))

I had a similar problem. Given a date, I wanted to get the date of the Monday of that week.

I used the following logic: Find the day number in the week in the range of 0-6, then subtract that from the originay date.

I used: DATEADD(day,-(DATEPART(weekday,)+5)%7,)

Since DATEPRRT(weekday,) returns 1 = Sundaye ... 7=Saturday, DATEPART(weekday,)+5)%7 returns 0=Monday ... 6=Sunday.

Subtracting this number of days from the original date gives the previous Monday. The same technique could be used for any starting day of the week.


I found this simple and usefull. Works even if first day of week is Sunday or Monday.

DECLARE @BaseDate AS Date

SET @BaseDate = GETDATE()

DECLARE @FisrtDOW AS Date

SELECT @FirstDOW = DATEADD(d,DATEPART(WEEKDAY,@BaseDate) *-1 + 1, @BaseDate)


Maybe I'm over simplifying here, and that may be the case, but this seems to work for me. Haven't ran into any problems with it yet...

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

반응형