あなたが日曜日ではなく月曜日を受け取っている理由に答えるには:
日付0に週数を追加しています。日付0とは何ですか?1900-01-01。1900-01-01の日は何でしたか?月曜。つまり、あなたのコードでは、1900年1月1日月曜日から何週間経過したのでしょうか。それを[n]と呼びましょう。では、[n]週を1900年1月1日月曜日に追加します。これが月曜日になることに驚かないでください。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
現在の設定に関係なく日曜日が必要な場合は、設定を変更した場合(またはコードが別の設定のユーザーに対して実行されている場合)に問題は発生しません。あなたはジャイブに、これら2つの答えをしたい場合は、関数を使用する必要がありんに依存し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
今、あなたにはたくさんの選択肢がありますが、どれが最も効果的ですか?大きな違いがあるとしたら驚きますが、これまでに提供されたすべての回答を収集し、2つのテストセットを実行しました。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がハイエンドで最速となるのを見て、私は少し驚きました。多分私はそれについていくつかのより徹底的なテストとブログを実行します...もし皆さんが私にあなたの関数を他の場所に公開することに異議がない場合は。
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
@@datefirst
設定に関係なく一定のままです。月曜日= 2の場合