わかりました、私はそれをテストしていませんが、それを行う最も効率的な方法は、とにかくデータベースにあると便利な集計テーブルを使用することだと思います。
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[num_seq]') AND type in (N'U'))
DROP TABLE [dbo].[num_seq];
SELECT TOP 100000 IDENTITY(int,1,1) AS n
INTO num_seq
FROM MASTER..spt_values a, MASTER..spt_values b;
CREATE UNIQUE CLUSTERED INDEX idx_1 ON num_seq(n);
次に、これを使用して、2つの日付の間の日付範囲を構築できます。インデックスを使用するだけなので高速です(実際、ループよりも高速であることが多いので、信じられます)
create procedure getDates
@eventId int
AS
begin
declare @startdate datetime
declare @enddate datetime
--- get the start and end date, plus the start of the month with the start date in
select @startdate=startdate,
@enddate=enddate
from events where eventId=@eventId
select
@startdate+n AS date,
from
dbo.num_seq tally
where
tally.n<datediff(@monthstart, @enddate) and
Datepart(dd,@startdate+n) between 15 and 21 and
Datepart(dw, @startdate+n) = '<day>'
開始日と終了日を取得する以外に、毎月3番目のxidは15日から21日までの間にある必要があります。その範囲の曜日の名前は一意である必要があるため、すぐに見つけることができます。
2番目の曜日名が必要な場合は、範囲を適切に変更するか、パラメーターを使用して計算します。
開始日を使用して日付テーブルを作成し、終了日になるまで(集計テーブルの数値のリストを介して)日を追加します。
それが役に立てば幸い!