Как получить таблицу дат между x и y в sql server 2005

Мне просто нужен быстрый способ (и желательно без использования цикла while) создания таблицы каждой даты между датой @x и датой @y, чтобы я мог оставить внешнее соединение с некоторыми таблицами статистики, некоторые из которых наверняка не будут иметь записей дней между ними, что позволяет мне отмечать пропущенные дни с помощью 0


person digiguru    schedule 18.09.2008    source источник
comment
Я полагаю, что вы ищете это сообщение в блоге.   -  person bdukes    schedule 18.09.2008
comment
Это грязно, но это делает работу   -  person digiguru    schedule 18.09.2008
comment
И он переносим на другие механизмы SQL (включая Server 2000). :)   -  person IDisposable    schedule 19.10.2009


Ответы (8)


Строго говоря, это не совсем ответ на ваш вопрос, но довольно аккуратно.

Предполагая, что вы можете жить с указанием количества дней после даты начала, использование Common Table Expression дает вам:

WITH numbers ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM numbers WHERE n < 500 )
    SELECT DATEADD(day,n-1,'2008/11/01') FROM numbers
    OPTION ( MAXRECURSION 500 )
person BigJump    schedule 18.09.2008
comment
Предложение Option не принимает переменную в качестве входных данных, поэтому необходимо знать, сколько дней на момент написания кода. В противном случае: забавная штука. - person Amy B; 19.09.2008
comment
Но предложение Where делает это, MAXRECURSION — это просто отработка отказа, если цикл заходит слишком далеко. - person digiguru; 19.09.2008
comment
Если вы не можете использовать CTE (как в SQL Server 2000), вы можете использовать то, что я написал здесь musingmarc.blogspot.com/2006/07/ - person IDisposable; 19.10.2009
comment
@BigJump Я не могу понять, что вы здесь делаете (я не SQL Pro). Можете ли вы дать краткое объяснение? Это работает только в SQL Server или его можно использовать в базе данных Postgres? - person ffleandro; 19.07.2012

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

select  ...
from    Calendar
        left outer join
        ...
where   Calendar.Date >= @x
and     Calendar.Date <= @y
person Garry Shutler    schedule 18.09.2008

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

person Charles Graham    schedule 18.09.2008

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

Лучшее, что у меня было, это временная таблица, а затем выбор дат, к которым я хотел присоединиться.

Блог, на который ссылается bduke, симпатичный, хотя я думаю, что решение для временной таблицы, возможно, более чистое решение.

person Dana    schedule 18.09.2008

Я нашел еще одну таблицу, в которой хранятся все даты (это посетители веб-сайта), так как насчет этого...

Declare @FromDate datetime,  
        @ToDate datetime  
Declare @tmpDates table   
            (StatsDate datetime)
Set @FromDate = DateAdd(day,-30,GetDate())
Set @ToDate = GetDate()

Insert Into  @tmpDates (StatsDate)
Select 
    distinct CAST(FLOOR(CAST(visitDate AS DECIMAL(12, 5))) AS DATETIME)
FROM tbl_visitorstats 
Where visitDate between @FromDate And @ToDate 
Order By CAST(FLOOR(CAST(visitDate AS DECIMAL(12, 5))) AS DATETIME) 


Select * FROM @tmpDates

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

person digiguru    schedule 18.09.2008

Небольшой поворот в ответе, указанном как https://stackoverflow.com/a/95728/395440. Позволяет указать дни, а также вычисляет диапазон до текущей даты.

DECLARE @startDate datetime
SET @startDate = '2015/5/29';

WITH number ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM dates WHERE n < DATEDIFF(Day, @startDate, GETDATE()) )
    SELECT DATEADD(day,n-1,@startDate) FROM number where
    datename(dw, DATEADD(day,n-1,@startDate)) in ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday')
    OPTION ( MAXRECURSION 500 )
person Adrian Russell    schedule 15.03.2016

Просто напишите цикл. Кто-то должен написать для этого цикл, будь то вы или SQL Server.

DECLARE @Dates TABLE
(
  TheDate datetime PRIMARY KEY
)
DECLARE @StartDate datetime, @EndDate datetime
SELECT @StartDate = '2000-01-01', @EndDate = '2010-01-01'


DECLARE @LoopVar int, @LoopEnd int    
SELECT @LoopEnd = DateDiff(dd, @StartDate, @EndDate), @LoopVar = 0


WHILE @LoopVar <= @LoopEnd
BEGIN
  INSERT INTO @Dates (TheDate)
  SELECT DateAdd(dd,@LoopVar,@StartDate)

  SET @LoopVar = @LoopVar + 1
END


SELECT *
FROM @Dates
person Amy B    schedule 18.09.2008

Просто: ГДЕ столбец > дата начала И столбец ‹ дата окончания

person Oli    schedule 18.09.2008
comment
Он пытается создать таблицу для левого внешнего соединения. Это не сделает то, что он хочет сделать. - person Charles Graham; 18.09.2008