Tolong, tolong, tolong gunakan tabel kalender. SQL Server tidak tahu apa-apa tentang hari libur nasional, acara perusahaan, bencana alam, dll. Tabel kalender cukup mudah dibuat, membutuhkan ruang yang sangat kecil, dan akan ada di memori jika cukup direferensikan.
Berikut adalah contoh yang membuat tabel kalender dengan tanggal 30 tahun (2000 -> 2029) tetapi hanya membutuhkan 200 KB pada disk (136 KB jika Anda menggunakan kompresi halaman). Itu hampir dijamin kurang dari pemberian memori yang diperlukan untuk memproses beberapa CTE atau set lain saat runtime.
CREATE TABLE dbo.Calendar
(
dt DATE PRIMARY KEY, -- use SMALLDATETIME if < SQL Server 2008
IsWorkDay BIT
);
DECLARE @s DATE, @e DATE;
SELECT @s = '2000-01-01' , @e = '2029-12-31';
INSERT dbo.Calendar(dt, IsWorkDay)
SELECT DATEADD(DAY, n-1, '2000-01-01'), 1
FROM
(
SELECT TOP (DATEDIFF(DAY, @s, @e)+1) ROW_NUMBER()
OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
) AS x(n);
SET DATEFIRST 1;
-- weekends
UPDATE dbo.Calendar SET IsWorkDay = 0
WHERE DATEPART(WEEKDAY, dt) IN (6,7);
-- Christmas
UPDATE dbo.Calendar SET IsWorkDay = 0
WHERE MONTH(dt) = 12
AND DAY(dt) = 25
AND IsWorkDay = 1;
-- continue with other holidays, known company events, etc.
Sekarang kueri yang Anda cari cukup sederhana untuk ditulis:
SELECT COUNT(*) FROM dbo.Calendar
WHERE dt >= '20130110'
AND dt < '20130115'
AND IsWorkDay = 1;
Info lebih lanjut tentang tabel kalender:
http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html
Info lebih lanjut tentang menghasilkan set tanpa loop:
http://www.sqlperformance.com/tag/date-ranges
Juga berhati-hatilah terhadap hal-hal kecil seperti mengandalkan keluaran bahasa Inggris dari DATENAME
. Saya telah melihat beberapa aplikasi rusak karena beberapa pengguna memiliki setelan bahasa yang berbeda, dan jika Anda mengandalkan WEEKDAY
pastikan Anda menyetel DATEFIRST
pengaturan dengan tepat...