집계 된 날짜를 요일로 저장하여 레코드를 주별로 그룹화하려고합니다. 그러나 날짜를 반올림하는 데 사용하는 표준 기술은 주 단위로 올바르게 작동하지 않는 것 같습니다 (일, 월, 년, 분기 및 내가 적용한 다른 기간에는 적용됨).
다음은 SQL입니다.
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);
이것은 2011-08-22 00:00:00.000
일요일이 아니라 월요일을 반환합니다 . 일요일의 코드 인 @@datefirst
returns를 선택하면 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″두 배 덕분에 훨씬 느려질 것입니다.
답변
직장에서 답변이 필요하고 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]. [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) 종료
답변
이 스크립트를 검색했습니다.
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
답변
아마도 이것이 필요할 것입니다.
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 반환 같이 시작 -DATEFIRST 설정 얻기 @ds int = @@ DATEFIRST 선언 -현재 DATEFIRST 설정에서 요일 번호 가져 오기 @dow int = DATEPART (dw, @ currentDate) 선언 DECLARE @wd int = 1 + (((@ dow + @ ds) % 7) +5) % 7-항상 Mon을 1로, Tue를 2로 ... Sun을 7로 반환합니다. 반환 날짜 ADD (dd, 1- @ wd, @ currentDate) 종료