2015-04-29 3 views
0

Я хочу заполнить столбец datetime на лету в хранимой процедуре. ниже - это запрос, который у меня сейчас есть, но это замедляет производительность запросов.Заполнение столбца Datetime

CREATE TABLE #TaxVal 
(
    ID   INT 
    , PaidDate DATETIME 
    , CustID INT 
    , CompID INT 
) 

INSERT INTO #TaxVal(ID, PaidDate, CustID, CompID) 
VALUES(01, '20150201',12, 100) 
    , (03,'20150301', 18,101) 
    , (10,'20150401',19,22) 
    , (17,'20150401',02,11) 
    , (11,'20150411',18,201) 
    , (78,'20150421',18,299) 
    , (133,'20150407',18,101) 

-- SELECT * FROM #TaxVal 

DECLARE @StartDate DATETIME = '20150101' 
    , @EndDate  DATETIME = '20150501' 

DECLARE @Tab TABLE 
(
    CompID INT 
    , DateField DATETIME 
) 

DECLARE @T INT 
SET @T = 0 
WHILE @EndDate >= @StartDate + @T 
BEGIN 
    INSERT INTO @Tab 
    SELECT CompID 
     , @StartDate + @T AS DateField 
    FROM #TaxVal 
    WHERE CustID = 18 
     AND CompID = 101 
    ORDER BY DateField DESC 

    SET @T = @T + 1 
END 

SELECT DISTINCT * FROM @Tab 

DROP TABLE #TaxVal 

Каков наилучший способ написать этот запрос для повышения производительности?

+0

Попробуйте использовать общее табличное выражение (CTE) или используйте таблицу_numbers_ для генерации набора дат и вставьте их за один раз. Поиск ** сервера sql генерирует даты **, чтобы вы начали. Совет. Полезно пометить вопросы базы данных как с помощью соответствующего программного обеспечения (MySQL, Oracle, DB2, ...) и версии, например. 'SQL-сервер-2014'. Различия в синтаксисе и особенностях часто влияют на ответы. – HABO

+0

Не могли бы вы привести пример. Спасибо – dLight

ответ

1

Изменить это:

DECLARE @T INT 
SET @T = 0 
WHILE @EndDate >= @StartDate + @T 
BEGIN 
    INSERT INTO @Tab 
SELECT CompID 
    , @StartDate + @T AS DateField 
FROM #TaxVal 
WHERE CustID = 18 
    AND CompID = 101 
ORDER BY DateField DESC 

SET @T = @T + 1 
END 

к этому:

;with cte as(
select cast('20150101' as date) as d 
union all 
select dateadd(dd, 1, d) as d from cte where d < '20150501' 
) 
INSERT INTO @Tab 
SELECT CompID, d 
FROM #TaxVal 
cross join cte 
WHERE CustID = 18 AND CompID = 101 
Option(maxrecursion 0) 

Вот recursive common table expression получить все даты в диапазоне. Затем вы делаете cross join и вставляете. Обратите внимание: нет смысла заказывать набор при вставке.

+0

Спасибо. Я получаю ошибку. Оператор завершен. Максимальная рекурсия 100 была исчерпана до завершения заявки. – dLight

+0

@dLight, см. Последние edites. Опция (maxrecurtion 0) –

0

ответ Джорджи из

;with cte as(
select cast('20150101' as date) as d 
union all 
select dateadd(dd, 1, d) as d from cte where d < '20150501' 
) 
INSERT INTO @Tab 
SELECT CompID, d 
FROM #TaxVal 
cross join cte 
WHERE CustID = 18 AND CompID = 101 

будет работать, но будьте осторожны с рекурсивным CTE-х. Если диапазон дат большой, вы быстро достигнете максимального уровня рекурсии. Часто таблица чисел используется так же, как упоминается HABO. Это просто таблица с одним столбцом, в которой есть только целое число, поэтому строки будут 1, 2, 3, 4, 5 и т. Д. Затем вы можете присоединиться к таблице Numbers (внешнее применение хорошо подходит для этого) и использовать числа с dateadd, чтобы получить ваши дополнительные даты. Также обратите внимание, что вы можете столкнуться с проблемой, когда таблица Numbers не содержит достаточно строк для диапазона дат.

+0

Чтобы не попасть в предел, используется опция (maxrecuraion 0). Thx, я вышел из своего ответа. –

Смежные вопросы