Мне просто нужен быстрый способ (и желательно без использования цикла while) создания таблицы каждой даты между датой @x и датой @y, чтобы я мог оставить внешнее соединение с некоторыми таблицами статистики, некоторые из которых наверняка не будут иметь записей дней между ними, что позволяет мне отмечать пропущенные дни с помощью 0
Как получить таблицу дат между x и y в sql server 2005
Ответы (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 )
Я бы создал таблицу календаря, которая просто содержала бы каждую дату от подходящей даты начала до подходящей даты окончания. Это не заняло бы много места в вашей базе данных и сделало бы эти типы запросов детской игрой.
select ...
from Calendar
left outer join
...
where Calendar.Date >= @x
and Calendar.Date <= @y
Я думаю, что вы могли бы просто сделать это в цикле while. Я знаю, что это уродливо, но это легко и это работает.
На самом деле я делал что-то подобное некоторое время назад, но я не мог придумать способ, который не использовал бы цикл.
Лучшее, что у меня было, это временная таблица, а затем выбор дат, к которым я хотел присоединиться.
Блог, на который ссылается bduke, симпатичный, хотя я думаю, что решение для временной таблицы, возможно, более чистое решение.
Я нашел еще одну таблицу, в которой хранятся все даты (это посетители веб-сайта), так как насчет этого...
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% будут данные на каждый день.
Небольшой поворот в ответе, указанном как 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 )
Просто напишите цикл. Кто-то должен написать для этого цикл, будь то вы или 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
Просто: ГДЕ столбец > дата начала И столбец ‹ дата окончания