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
'programing' 카테고리의 다른 글
| UI Navigation Controller "뒤로 버튼" 사용자 지정 텍스트? (0) | 2023.06.04 |
|---|---|
| Azure Function App에서 Azure 스토리지 큐 조절 처리 (0) | 2023.05.25 |
| MongoDB 및 Nodejs를 사용한 날짜 삽입 및 쿼리 (0) | 2023.05.25 |
| Bash에서 하위 문자열 추출 (0) | 2023.05.25 |
| 다른 지점으로 전환하려면 어떻게 해야 합니까? (0) | 2023.05.25 |