0

SQL Server 2008 データベースに、Hours と Starts という実行中の合計を保持する 2 つの列を持つテーブルがあります。もう 1 つの列 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

テーブルをクエリして、指定された 2 つの年の間の各月の総時間数と開始時間を取得するにはどうすればよいですか? (この場合は 2011 年と 2013 年です。) 1 か月の最後のレコードから値を取得し、前月の最後のレコードから値を差し引く必要があることはわかっています。ただし、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 条件を使用して、ContainterID ごとに翌月の値を取得できます。

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 に答える