2

というテーブルVolumeRequestには、日付範囲のアカウントごとのボリューム リクエストが格納されます。

AccountId   StartDate                       EndDate                   DailyVolume
670         2013-07-01 00:00:00.000         2013-07-31 00:00:00.000   10
670         2013-07-01 00:00:00.000         2013-07-31 00:00:00.000   1050
670         2013-07-10 00:00:00.000         2013-07-10 00:00:00.000   -350
670         2013-07-24 00:00:00.000         2013-07-26 00:00:00.000   -350
673         2013-06-01 00:00:00.000         2013-07-31 00:00:00.000   233

リクエストを毎日表示する必要があります。7 月のレポートのように、特定の日付範囲のアカウントごとにボリュームが日ごとに合計されます。レポートは次のようになります。ボリューム リクエストの日付の開始日と終了日は、指定されたレポートの日付に合わせて調整する必要があります

AccountId   Date                         Volume
670         2013-07-01 00:00:00.000      1060
670         2013-07-02 00:00:00.000      1060
.
.
670         2013-07-10 00:00:00.000      710
.
.
670         2013-07-24 00:00:00.000      710
670         2013-07-25 00:00:00.000      710
670         2013-07-26 00:00:00.000      710
.
.
670         2013-07-31 00:00:00.000      1060
673         2013-07-01 00:00:00.000      233
.
.
673         2013-07-31 00:00:00.000      233

現在、テーブル変数とループを使用してそれを達成していますが、これは良いコーディング方法ではありません。

DECLARE @sDate DATETIME, @eDate DATETIME , @volume DECIMAL (10, 4),  rstartdate DATETIME, @renddate   DATETIME , @loopcount   INT
SET @sdate = '4/1/2013'
SET @edate = '4/30/2013'

DECLARE @VolumeRequest TABLE 
  ( 
     ID        INT IDENTITY (1, 1) PRIMARY KEY, 
     Aid       INT, 
     Startdate DATETIME, 
     Enddate   DATETIME, 
     volume    DECIMAL (14, 4) 
  ) 
DECLARE @DailyRequest TABLE 
  ( 
     ID        INT IDENTITY (1, 1) PRIMARY KEY, 
     Accountid INT, 
     ReadDate  DATETIME, 
     Volume    DECIMAL (14, 4) 
  ) 

    INSERT INTO @VolumeRequest 
      SELECT Accountid, 
             ( CASE 
                 WHEN @sdate > startdate THEN @sdate 
                 ELSE startdate 
               END ), 
             ( CASE 
                 WHEN @edate < enddate THEN @edate 
                 ELSE enddate 
               END ), 
             dailyvolume 
      FROM   VolumeRequest 
      WHERE  Startdate <= @edate 
             AND Enddate >= @sdate 
             AND isnull (deprecated, 0) != 1 

      --loop to breakdown the volume requests into daily requests 
      SET @loopcount = 1

      WHILE @loopcount <= (SELECT MAX(ID) 
                                FROM   @VolumeRequest) 
        BEGIN 
            SELECT @volume = volume, 
                   @rstartdate = Startdate, 
                   @renddate = Enddate 
            FROM   @VolumeRequest 
            WHERE  ID = @loopcount 

            WHILE @rstartdate <= @renddate 
              BEGIN 
                  INSERT INTO @DailyRequest 
                  SELECT @currentaid, 
                         @rstartdate, 
                         @volume 

                  SET @rstartdate = DATEADD(day, 1, @rstartdate) 
              END 

            SET @LoopCount = @LoopCount + 1 
        END

ループやカーソルを使用しない方法を探しています。同様の質問を見つけました。そこの答えは私を助けませんでした。

4

2 に答える 2

1

SQLFiddle デモ

WITH 句と再帰を使用Daysして、MIN と MAX の日付の間のすべての日を含むテーブルを生成します。Accounts次に、固有のテーブルを生成しますAccountID。最後に、これらすべてのテーブルを JOIN し、すべてを SUM でグループ化します。

WITH MINMAX as 
( SELECT MIN(StartDate) as MinDate,
         MAX(EndDate) as MaxDate
  from T
),
DAYS as
( SELECT MinDate as D from MINMAX
  UNION ALL
  SELECT D+1 as D FROM DAYS WHERE D+1<=
    (
      SELECT MaxDate FROM MINMAX  
     )
),
Accounts as 
(
  select distinct AccountID from T
) 

select A.AccountId,Days.D,sum(T.DailyVolume) from Days
CROSS JOIN Accounts A 
JOIN T on A.AccountID=T.AccountID
          AND
          Days.D between T.StartDate and T.EndDate
GROUP BY A.AccountId,Days.D
ORDER BY A.AccountId,Days.D
OPTION (MAXRECURSION 10000)
于 2013-08-09T17:16:15.193 に答える