TSQL - 控制数字序列

时间:2014-03-31 00:50:50

标签: tsql sql-server-2012

我是TSQL的新手。 我有一张桌子,里面有一辆名为ODOMETER的车辆。我必须在从1月1日到结束的一段时间内得到公里数。 SELECT MAX(里程表) - MIN(里程表)为TotalKm FROM Table 这将在理想的测试场景中起作用,但Odomometer可以在任何时间重置为0。 有人可以帮忙解决我的问题,谢谢。

我正在使用MS SQL 2012

记录示例:

 Date          Odometer value
 datetime var, 37210
 datetime var, 37340
 datetime var, 0
 datetime var, 220

2 个答案:

答案 0 :(得分:2)

使用LAG尝试这样的事情。还有其他方法,但这应该很容易。

编辑:更改样本数据以包括所需月份范围之外的记录。还简化了阅读以便于手动计算。将显示OP的第二个选项。

DECLARE @tbl TABLE (stamp DATETIME, Reading INT)
INSERT INTO @tbl VALUES 
  ('02/28/2014',0)
 ,('03/01/2014',10)
 ,('03/10/2014',20)
 ,('03/22/2014',0)
 ,('03/30/2014',10)
 ,('03/31/2014',20)
 ,('04/01/2014',30)

--Original solution with WHERE on the "outer" SELECT.
--This give a result of 40 as it include the change of 10 between 2/28 and 3/31. 

;WITH cte AS (
   SELECT Reading
         ,LAG(Reading,1,Reading) OVER (ORDER BY stamp ASC) LastReading
         ,Reading - LAG(Reading,1,Reading) OVER (ORDER BY stamp ASC) ChangeSinceLastReading 
         ,CONVERT(date, stamp) stamp
     FROM @tbl
)
SELECT SUM(CASE WHEN Reading = 0 THEN 0 ELSE ChangeSinceLastReading END)
  FROM cte
 WHERE stamp BETWEEN '03/01/2014' AND '03/31/2014'

--Second option with WHERE on the "inner" SELECT (within the  CTE)
--This give a result of 30 as it include the change of 10 between 2/28 and 3/31 is by the filtered lag.

;WITH cte AS (
   SELECT Reading
         ,LAG(Reading,1,Reading) OVER (ORDER BY stamp ASC) LastReading
         ,Reading - LAG(Reading,1,Reading) OVER (ORDER BY stamp ASC) ChangeSinceLastReading 
         ,CONVERT(date, stamp) stamp
     FROM @tbl
    WHERE stamp BETWEEN '03/01/2014' AND '03/31/2014'
)
SELECT SUM(CASE WHEN Reading = 0 THEN 0 ELSE ChangeSinceLastReading END)
  FROM cte

答案 1 :(得分:0)

我认为使用LAG的Karl解决方案比我的好,但无论如何:

;WITH [Rows] AS
(
    SELECT o1.[Date], o1.[Value] as CurrentValue, 
                (SELECT TOP 1 o2.[Value] 
                FROM @tbl o2 WHERE o1.[Date] < o2.[Date]) as NextValue
    FROM @tbl o1
)
SELECT SUM (CASE WHEN [NextValue] IS NULL OR [NextValue] < [CurrentValue] THEN 0 ELSE [NextValue] - [CurrentValue] END )
FROM [Rows]