その場で計算するための関数は次のとおりです。
CREATE FUNCTION dbo.WholeWeekFromDate (
@Date datetime
)
RETURNS tinyint
AS BEGIN
RETURN (
SELECT DateDiff(Day, DateAdd(Year, DateDiff(Year, 0, CalcDate), 0), CalcDate) / 7 + 1
FROM (SELECT DateAdd(Day, (DateDiff(Day, 0, @Date) + 1) / 7 * 7, 0)) X (CalcDate)
);
END;
行ごとに1回呼び出されるため、パフォーマンスが低下する可能性があるため、使用することはお勧めしません。実際のクエリで使用する関数がどうしても必要な場合は、それを単一の列と行を返すインライン関数に変換し、そのまま使用します。
SELECT
OtherColumns,
(SELECT WeekNumber FROM dbo.WholeWeekFromDate(DateColumn)) WeekNumber
FROM
YourTable;
これにより、実行計画で「インライン化」され、パフォーマンスが大幅に向上します。
しかし、他の人が示唆しているように、BusinessDate テーブルを使用することはさらに良いことです。これはあなたのために作成するための有利なスタートです:
CREATE TABLE dbo.BusinessDate (
BusinessDate date NOT NULL CONSTRAINT PK_BusinessDate PRIMARY KEY CLUSTERED,
WholeWeekYear smallint NOT NULL
CONSTRAINT CK_BusinessDate_WholeWeekYear_Valid
CHECK (WholeWeekYear BETWEEN 1900 AND 9999),
WholeWeekNumber tinyint NOT NULL
CONSTRAINT CK_BusinessDate_WholeWeekNumber_Valid
CHECK (WholeWeekNumber BETWEEN 1 AND 53),
Holiday bit CONSTRAINT DF_BusinessDate_Holiday DEFAULT (0),
Weekend bit CONSTRAINT DF_BusinessDate_Weekend DEFAULT (0),
BusinessDay AS
(Convert(bit, CASE WHEN Holiday = 0 AND Weekend = 0 THEN 1 ELSE 0 END)) PERSISTED
);
さらに、1900-01-01 から 2617-09-22 までのデータを入力します (製品の予想される耐用年数には十分ですか? 7.8 MB しかないので、サイズが大きくても心配する必要はありません)。
WITH A (N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1),
B (N) AS (SELECT 1 FROM A F, A A, A L, A C, A O, A N),
C (N) AS (SELECT Row_Number() OVER (ORDER BY (SELECT 1)) FROM B),
Dates AS (
SELECT
N,
DateAdd(Day, N, '18991231') Dte,
DateAdd(Day, N / 7 * 7, '19000101') CalcDate
FROM C
)
INSERT dbo.BusinessDate
SELECT
Dte,
Year(CalcDate),
DateDiff(Day, DateAdd(Year, DateDiff(Year, 0, CalcDate), 0), CalcDate) / 7 + 1,
0,
(N + 6) % 7 / 5 -- calculate weekends
FROM Dates; -- 3-7 seconds or so on my VM server
次に、その日付でテーブルに結合し、WholeWeekNumber 列を出力に使用します。これがないと、2009-01-01 の 52 が実際に 2008 年に属していることを理解するのが少し難しくなるので、WeekNumberYear を追加することも検討してください。笑う)。
テーブルの内容の例:
BusinessDate WholeWeekYear WholeWeekNumber Holiday Weekend BusinessDay
------------ ------------- --------------- ------- ------- -----------
1/1/2009 2008 52 0 0 1
1/2/2009 2008 52 0 0 1
1/3/2009 2008 52 0 1 0
1/4/2009 2009 1 0 1 0
1/5/2009 2009 1 0 0 1
1/6/2009 2009 1 0 0 1
1/7/2009 2009 1 0 0 1
1/8/2009 2009 1 0 0 1
1/9/2009 2009 1 0 0 1
1/10/2009 2009 1 0 1 0
1/11/2009 2009 2 0 1 0
これを一般的な営業日計算テーブルとして使用したくない場合は、最後の 3 列を削除できます。それ以外の場合は、Holiday 列を会社の休日の 1 に更新します。
注: 上記のテーブルを実際に作成し、そのテーブルへのアクセスで 以外の列で JOIN または WHERE 条件を使用することが最も多い場合はBusinessDate
、主キーを非クラスター化し、代替列から始まるクラスター化インデックスを追加します。
上記のスクリプトの一部には、SQL 2005 以降が必要です。