3-й день <day_of_week> месяца - MySQL - PullRequest
1 голос
/ 30 августа 2010

Я работаю над приложением повторения событий.У меня есть диапазон дат, скажем, с 1 января 2010 года по 31 декабря 2011 года. Я хочу эффективно возвращать все 3 четверга (произвольно) каждого месяца.Я мог бы сделать это довольно тривиально в коде, предостережение в том, что это должно быть выполнено в хранимой процедуре.В конечном итоге я бы хотел что-то вроде:

CALL return_dates(event_id);

Этот event_id имеет начальную дату 01.01.2010 и конечную дату 31.12.2011.Результирующий набор будет выглядеть примерно так:

1/20/2010
2/14/2010
3/17/2010
4/16/2010
5/18/2010
etc. 

Мне просто любопытно, каким будет самый эффективный способ сделать это, учитывая, что в моем реальном использовании может оказаться очень большой набор результатов.*

Ответы [ 2 ]

1 голос
/ 30 августа 2010

Одна мысль, которая приходит в голову - вы можете создать таблицу и хранить там интересующие вас даты.

0 голосов
/ 02 сентября 2010

Хорошо, я не проверял это, но я думаю, что наиболее эффективный способ сделать это - через таблицу подсчета, которую в любом случае полезно иметь в БД:

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);

Вы можетезатем используйте это, чтобы построить диапазон дат между двумя датами.Это быстро, потому что он просто использует индекс (на самом деле часто быстрее, чем цикл, так что я вынужден поверить)

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>'

Помимо получения даты начала и окончания, третий x id каждый месяц долженбыть между 15-м и 21-м включительно.Имена дней в этом диапазоне должны быть уникальными, поэтому мы можем сразу их найти.

Если вы хотели получить второе имя дня, просто измените диапазон соответствующим образом или используйте параметр для его вычисления.

Он создает таблицу дат с использованием начальной даты, а затем добавляет дни (через список чисел в таблице подсчета), пока не достигнет конечной даты.

Надеюсь, это поможет!

...