填充日期时间列
Populating a Datetime Column
我想在存储过程中动态填充日期时间列。下面是我目前拥有的查询,它执行相同但会降低查询性能。
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
编写此查询以获得更好性能的最佳方式是什么?
改变这个:
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
并插入。请注意,插入时设置顺序是没有意义的。
Giorgi 的回答
;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。如果日期范围很大,您将很快达到最大递归级别。通常,数字 table 的用法很像 HABO 提到的。这只是一个 table 的单列,只有一个整数,因此行将是 1、2、3、4、5 等。然后您可以加入数字 table(外部应用效果很好为此)并使用带有 dateadd 的数字来获取增量日期。另请注意,您可以 运行 遇到数字 table 没有包含足够的行来满足您的日期范围的问题。
我想在存储过程中动态填充日期时间列。下面是我目前拥有的查询,它执行相同但会降低查询性能。
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
编写此查询以获得更好性能的最佳方式是什么?
改变这个:
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
并插入。请注意,插入时设置顺序是没有意义的。
Giorgi 的回答
;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。如果日期范围很大,您将很快达到最大递归级别。通常,数字 table 的用法很像 HABO 提到的。这只是一个 table 的单列,只有一个整数,因此行将是 1、2、3、4、5 等。然后您可以加入数字 table(外部应用效果很好为此)并使用带有 dateadd 的数字来获取增量日期。另请注意,您可以 运行 遇到数字 table 没有包含足够的行来满足您的日期范围的问题。