我正在尝试在SQL Server中进行一些复杂的操作。为了防止任何性能损失,我试图在数据库端进行所有操作。
以下是我在C#中的查询
"DECLARE @t AS TABLE (StartTime DATETIME, EndTime DateTime, Value REAL, V1 REAL, V2 REAL) " +
"DECLARE @i AS DateTime = @startDate " +
"WHILE @i <= @endDate " +
"BEGIN " +
"DECLARE @min AS Real = " +
"(SELECT TOP 1 RawStatus FROM CustomPollerStatistics_Detail " +
"WHERE RawStatus IS NOT NULL AND CustomPollerAssignmentID = @pollerID " +
"AND [DateTime] <= @i ORDER BY [DateTime] DESC) " +
"DECLARE @max AS Real = " +
"(SELECT TOP 1 RawStatus FROM CustomPollerStatistics_Detail " +
"WHERE RawStatus IS NOT NULL AND CustomPollerAssignmentID = @pollerID " +
"AND [DateTime] <= DATEADD(MI, @interval, @i) ORDER BY [DateTime] DESC) " +
"INSERT INTO @t VALUES (@i, DATEADD(MI, @interval, @i), @max - @min, @min, @max) " +
"SET @i = DATEADD(MI, @interval, @i) " +
"END " +
"SELECT * FROM @t";
我在调试模式下仔细检查了参数的值。我尝试使用相同的参数运行查询,方法是在SQL Server Management Studio中使用C#传递的相同值在查询顶部声明它,在这种情况下,它会按预期生成正确的结果。我已按以下方式添加参数。
com.Parameters.Add("@pollerID", System.Data.SqlDbType.UniqueIdentifier).Value = assignmentID;
com.Parameters.Add("@interval", System.Data.SqlDbType.Int).Value = accuracyMinutes;
com.Parameters.Add("@startDate", System.Data.SqlDbType.DateTime).Value = startDate;
com.Parameters.Add("@endDate", System.Data.SqlDbType.DateTime).Value = endDate;
当我从C#运行此查询时,列@max - @min, @min, @max
(第3列,第4列和第5列)总是评估为0
。我无法自己找出原因。请帮忙。见下面的截图。
示例数据https://github.com/scipy/scipy/pull/3574。 C#代码http://pastebin.com/raw.php?i=QuBCSRw3。
答案 0 :(得分:1)
首先,理想情况下,数据库中应该有两个带有索引的标准表。我看到有60-70%的报告使用这些表格。
这些将帮助您解决报告中的性能问题。
如果您不能,请先使用以下脚本生成日期时间范围。这将运行n次迭代,即2 ^ n
DROP TABLE #tbl;
CREATE TABLE #tbl( num INT,
startDt DATETIME2( 0 ),
endDt DATETIME2( 0 ),
dateWithMin AS DATEADD( mi,num,startDt ) PERSISTED
PRIMARY KEY
--will create clustered index for performance
);
DECLARE @startDt DATETIME2( 0 ) = GETDATE(),
@endDt DATETIME2( 0 ) = DATEADD( Mi,15,GETDATE());
DECLARE @rc INT = 1,
@max INT = DATEDIFF( MI,@startDt,@endDt );
SELECT @rc,
@max;
INSERT INTO #tbl
VALUES( 0,@startDt,@endDt );
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO #tbl
SELECT num + @rc,
@startDt,
@endDt
FROM #tbl;
SET @rc = @rc * 2;
END;
INSERT INTO #tbl
SELECT num + @rc,
@startDt,
@endDt
FROM #tbl
WHERE num + @rc <= @max;
SELECT *
FROM #tbl;
这会产生类似这样的结果
+-----+---------------------+---------------------+---------------------+
| num | startDt | endDt | dateWithMin |
+-----+---------------------+---------------------+---------------------+
| 0 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:37:24 |
| 1 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:38:24 |
| 2 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:39:24 |
| 3 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:40:24 |
| 4 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:41:24 |
| 5 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:42:24 |
| 6 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:43:24 |
| 7 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:44:24 |
| 8 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:45:24 |
| 9 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:46:24 |
| 10 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:47:24 |
| 11 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:48:24 |
| 12 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:49:24 |
| 13 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:50:24 |
| 14 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:51:24 |
| 15 | 2015-05-22 19:37:24 | 2015-05-22 19:52:24 | 2015-05-22 19:52:24 |
+-----+---------------------+---------------------+---------------------+
假设您每分钟都有数据,以下查询应该会给您结果。否则你需要一个如上所述的时间序列表。
修改强>
SELECT dt,
mini,
maxi,
(
SELECT RawStatus
FROM CustomPollerStatistics_Detail
WHERE [DateTime] = maxi ) - (
SELECT RawStatus
FROM CustomPollerStatistics_Detail
WHERE [DateTime] = mini ) AS PowerConsumed
INTO #tmp
FROM(
SELECT DATEADD( Mi,DATEDIFF( Mi,0,[DateTime] ),0 ) AS dt,
MIN( [DateTime] ) mini,
MAX( [DateTime] ) maxi
FROM CustomPollerStatistics_Detail t
WHERE [DateTime] BETWEEN @StartDate AND @EndDate
GROUP BY DATEADD( Mi,DATEDIFF( Mi,0,[DateTime] ),0 )) x;
SELECT l.dt,
DATEADD( Mi,@TimeInterval,l.dt ) AS NextDt,
SUM( PowerConsumed ) AS Total
FROM #tmp l
WHERE l.dt BETWEEN l.dt AND(
SELECT TOP 1 r.maxi AS NextDt
FROM #tmp r
WHERE r.dt = l.dt
ORDER BY r.maxi DESC )
GROUP BY l.dt,
DATEADD( Mi,@TimeInterval,l.dt );