这是我的sql脚本
CREATE TABLE dbo.calendario (
datacal DATETIME NOT NULL PRIMARY KEY,
horautil BIT NOT NULL DEFAULT 1
);
-- DELETE FROM dbo.calendario;
DECLARE @dtmin DATETIME, @dtmax DATETIME, @dtnext DATETIME;
SELECT
@dtmin = '2014-03-11 00:00:00'
, @dtmax = '2030-12-31 23:50:00'
, @dtnext = @dtmin;
WHILE (@dtnext <= @dtmax) BEGIN
INSERT INTO dbo.calendario(datacal) VALUES (@dtnext);
SET @dtnext = DATEADD(MINUTE, 10, @dtnext);
END;
基本上,我想创建一个日期间隔为10分钟的表格。循环插入了很多记录,但我认为执行它会很快。这需要几分钟......
我正在使用sql server 2008 r2。
感谢任何帮助。
答案 0 :(得分:8)
你应该避免循环等,并尝试接近这个基于集合。 (谷歌搜索“RBAR SQL”)
无论如何,这在我的笔记本电脑上以1秒的速度运行:
DROP TABLE dbo.calendario
GO
CREATE TABLE dbo.calendario (
datacal DATETIME NOT NULL PRIMARY KEY,
horautil BIT NOT NULL DEFAULT 1
);
-- DELETE FROM dbo.calendario;
DECLARE @dtmin DATETIME, @dtmax DATETIME, @intervals int
SELECT @dtmin = '2014-03-11 00:00:00'
, @dtmax = '2030-12-31 23:50:00'
SELECT @intervals = DateDiff(minute, @dtmin, @dtmax) / 10
;WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
L6 AS(SELECT 1 AS c FROM L5 AS A, L5 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L6)
INSERT INTO dbo.calendario(datacal)
SELECT DateAdd(minute, 10 * (n - 1), @dtmin)
FROM Nums
WHERE n BETWEEN 1 AND @intervals + 1
-- SELECT * FROM dbo.calendario ORDER BY datacal
答案 1 :(得分:1)
此代码在我的机器上需要23秒(并且大部分都在排序中)
DECLARE @DateMin AS datetime = '2014-03-11 00:00:00';
DECLARE @DateMax AS datetime = '2030-12-31 23:50:00';
DECLARE @Test AS Table (
datacal DATETIME NOT NULL PRIMARY KEY
);
WITH Counter AS (
SELECT ROW_NUMBER() OVER (ORDER BY a.object_id) -1 AS Count
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b
)
INSERT INTO @Test (datacal)
SELECT DATEADD(minute, 10 * Count, @DateMin)
FROM Counter
WHERE DATEADD(minute, 10 * Count, @DateMin) <= @DateMax
答案 2 :(得分:1)
已经有一些有趣的答案。这是另一个基于集合的选项,它也使用公共表表达式。
DECLARE @StartDate DATETIME = '2014-03-11 00:00:00';
DECLARE @EndDate DATETIME = '2030-12-31 00:00:00';
--CTE of days in the Start/End date range.
WITH DaysTable AS
(
SELECT @StartDate AS CalendarDate
UNION ALL
SELECT DATEADD(dd, 1, CalendarDate)
FROM DaysTable
WHERE CalendarDate < @EndDate
)
--CTE of 10 min intervals for one day.
,MinsTable AS
(
SELECT CAST(0 AS DATETIME) MinutesDate
UNION ALL
SELECT DATEADD(MINUTE, 10, mt.MinutesDate)
FROM MinsTable mt
WHERE MinutesDate < DATEADD(MINUTE, -10, CAST(0 AS DATETIME) + 1)
)
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, CAST(0 AS DATETIME), mt.MinutesDate), dt.CalendarDate) Every10Min
INTO #TestTable
FROM MinsTable mt
--Cross join for all 10 min intervals of all days in date range.
CROSS JOIN DaysTable dt
ORDER BY DATEADD(MINUTE, DATEDIFF(MINUTE, CAST(0 AS DATETIME), mt.MinutesDate), dt.CalendarDate)
OPTION (MAXRECURSION 32767)
SELECT *
FROM #TestTable