从c#执行相同查询时的结果不同(不正确)

时间:2015-05-22 13:42:10

标签: c# sql-server sqlparameters

我正在尝试在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。我无法自己找出原因。请帮忙。见下面的截图。

enter image description here

示例数据https://github.com/scipy/scipy/pull/3574。 C#代码http://pastebin.com/raw.php?i=QuBCSRw3

1 个答案:

答案 0 :(得分:1)

首先,理想情况下,数据库中应该有两个带有索引的标准表。我看到有60-70%的报告使用这些表格。

  1. 表示日期,即1900-01-01至2079-06-06(smalldatetime)最大值 范围
  2. 号码表(1到1百万)
  3. 这些将帮助您解决报告中的性能问题。

    如果您不能,请先使用以下脚本生成日期时间范围。这将运行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 );