0

我在 SQL Server 2008 数据库中有一个表,其中两列保存运行总计,称为 Hours 和 Starts。另一列 Date 保存记录的日期。这些日期在任何给定的月份都是零星的,但总是有一个记录在该月的最后一个小时。

例如:

ContainerID | Date             | Hours | Starts

1           | 2010-12-31 23:59 | 20    | 6
1           | 2011-01-15 00:59 | 23    | 6
1           | 2011-01-31 23:59 | 30    | 8

2           | 2010-12-31 23:59 | 14    | 2
2           | 2011-01-18 12:59 | 14    | 2
2           | 2011-01-31 23:59 | 19    | 3

如何查询表以获取两个指定年份之间每个月的总小时数和开始数?(在这种情况下是 2011 年和 2013 年。)我知道我需要从一个月的最后一条记录中获取值,然后减去上个月最后一条记录中的值。但是,我很难想出在 SQL 中执行此操作的好方法。

根据要求,以下是预期结果:

ContainerID | Date             | MonthlyHours | MonthlyStarts
1           | 2011-01-31 23:59 | 10           | 2
2           | 2011-01-31 23:59 | 5            | 1
4

2 回答 2

0

尝试这个:

SELECT  c1.ContainerID, 
        c1.Date, 
        c1.Hours-c3.Hours AS "MonthlyHours", 
        c1.Starts - c3.Starts AS "MonthlyStarts"
FROM Containers c1
LEFT OUTER JOIN Containers c2 ON
                                c1.ContainerID = c2.ContainerID
                            AND datediff(MONTH, c1.Date, c2.Date)=0
                            AND c2.Date > c1.Date
    LEFT OUTER JOIN Containers c3 ON
                                    c1.ContainerID = c3.ContainerID
                                AND datediff(MONTH, c1.Date, c3.Date)=-1
    LEFT OUTER JOIN Containers c4 ON
                                    c3.ContainerID = c4.ContainerID
                                AND datediff(MONTH, c3.Date, c4.Date)=0
                                AND c4.Date > c3.Date
    WHERE 
            c2.ContainerID is null
        AND c4.ContainerID is null
        AND c3.ContainerID is not null
ORDER BY c1.ContainerID, c1.Date
于 2013-08-08T15:07:43.633 回答
-1

使用递归 CTE和一些“创造性”的 JOIN 条件,您可以获取每个 ContainerID 下个月的值:

WITH CTE_PREP AS 
(
    --RN will be 1 for last row in each month for each container 
    --MonthRank will be sequential number for each subsequent month (to increment easier)
    SELECT 
        *
        ,ROW_NUMBER() OVER (PARTITION BY ContainerID, YEAR(Date), MONTH(DATE) ORDER BY Date DESC) RN
        ,DENSE_RANK() OVER (ORDER BY YEAR(Date),MONTH(Date)) MonthRank
    FROM Table1
)
, RCTE AS 
(
    --"Zero row", last row in decembar 2010 for each container
    SELECT *, Hours AS MonthlyHours, Starts AS MonthlyStarts
    FROM CTE_Prep
    WHERE YEAR(date) = 2010 AND MONTH(date) = 12 AND RN = 1 

    UNION ALL

    --for each next row just join on MonthRank + 1
    SELECT t.*, t.Hours - r.Hours, t.Starts - r.Starts
    FROM RCTE r
    INNER JOIN CTE_Prep t ON r.ContainerID = t.ContainerID AND r.MonthRank + 1 = t.MonthRank AND t.Rn = 1
)
SELECT ContainerID, Date, MonthlyHours, MonthlyStarts
FROM RCTE
WHERE Date >= '2011-01-01' --to eliminate "zero row"
ORDER BY ContainerID

SQLFiddle DEMO(我添加了 2 月和 3 月的一些数据,以便测试不同月份的长度)

旧版小提琴

于 2013-08-08T15:06:14.513 回答