1

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

CALL return_dates(event_id); 

Это event_id имеет START_DATE в 1/1/2010 и END_DATE от 12/31/2011. Результат набора будет что-то вроде:

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

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

ответ

1

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

+0

Я бы предпочел сделать это динамически. Я полагаю, что это последняя возможность, но количество записей может быть абсурдно высоким. – JamesB41

+0

Количество записей зависит от диапазона, который вы хотите поддержать. Это не должно быть вопросом пространства, если вам нужно всего лишь несколько тысяч лет. Эффективность не должна вызывать беспокойства. Если запросами являются диапазоны и диапазон, это приблизительно год, когда хранение дат в таблице кажется приемлемым и эффективным решением. – Leonid

+0

Не вижу ничего плохого, если вы храните строку в месяц за 2000 лет в таблице. Это 24000 строк за 2000 лет, и у вас будут эффективные запросы диапазона. – Leonid

0

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

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 [email protected] 

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

Помимо получения даты начала и окончания, то третий й идентификатор каждого месяц должен быть между 15 и 21 включительно. Названия дней в этом диапазоне должны быть уникальными, поэтому мы можем найти его сразу.

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

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

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