2016-11-30 8 views
3

私は毎日プロバイダとアクティブなクライアントの合計を表示するこのテーブルを持っています。SQL Serverのセットベースのアプローチでwhileループを置き換えます

DailyClientPopulationテーブル:

Provider Activeclients DateAdded 
------- ------------- --------- 
p1   10   2016-11-01 
p1   15   2016-11-02 
p2   14   2016-11-01 
. 
. 
p1   70   2016-11-30 
p2   50   2016-11-30 

結果は、私たちが毎月の前半と後半に配置されたクライアントの平均数を表示する必要がthis.meansようにする必要があります。

TEMPBIWEEKLYCENSUSテーブル:

Provider Avg(activeclients) Biweeklyrange 
-------- ----------------- ------------- 
p1   30     11/01-11/15 
p2   20     11/01-11/15 
p1   40     11/15-11/30 
p2   30     11/15-11/30 

私は、開始日と現在の終了日の値を更新results.andを表示するには、ループしながら、使用しています。例:11月上旬、開始日= 11/01、現在終了日= 11/15の場合

終了日=月末。

これはコードです:

DECLARE @STARTDATE DATETIME 
DECLARE @ENDDATE DATETIME 
DECLARE @CURRENTENDDATE DATETIME 
DECLARE @MONTHLASTDATE DATETIME 
DECLARE @DAYSTOADD INT 
DECLARE @TEMPSTARTDATE DATETIME 

SET @STARTDATE= CONVERT(DATE, DATEADD(DAY, [email protected]*15,GETDATE())) 
--PRINT @STARTDATE 
SET @STARTDATE = DATEADD(MONTH,DATEDIFF(MONTH, 0, @STARTDATE),0) 
--PRINT @STARTDATE 
SET @ENDDATE = CONVERT(DATE,DATEADD(MONTH,1,GETDATE())) 
SET @ENDDATE = DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, @ENDDATE),0)) 
--PRINT @ENDDATE 

DECLARE @TEMPBIWEEKLYCENSUS table (ProviderName NVARCHAR(500), ActiveClients INT, BiWeeklyRange NVARCHAR(50) ); 
-- SET @MONTHLASTDATE =DATEADD(DAY,-1, DATEADD(MONTH,1,@STARTDATE)) 

WHILE (@STARTDATE <= @ENDDATE) 
BEGIN 
    SET @MONTHLASTDATE = DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, @STARTDATE), 0))) 
    -- PRINT DATEDIFF(DAY,@STARTDATE, @MONTHLASTDATE) 

    IF DATEDIFF(DAY, @STARTDATE, @MONTHLASTDATE) > 15 
    BEGIN 
     IF DATEDIFF(DAY, @STARTDATE, @MONTHLASTDATE)/2 = 15 
     BEGIN 
      SET @DAYSTOADD = 15 
     END 
     ELSE 
     BEGIN 
      SET @DAYSTOADD = 14 
     END 
    END 
    ELSE IF DATEDIFF(DAY, @STARTDATE, @MONTHLASTDATE) < 15 
    BEGIN 
     SET @DAYSTOADD = DATEDIFF(DAY,@STARTDATE, @MONTHLASTDATE) 
    END 

    SET @CURRENTENDDATE = CONVERT(DATE,DATEADD(DAY,@DAYSTOADD,@STARTDATE)) 
    --PRINT '**************************************' 
    --PRINT 'STARTDATE' 
    --PRINT @STARTDATE 
    --PRINT 'CURRENTENDDATE' 
    --PRINT @CURRENTENDDATE 
    --PRINT '**************************************' 

    INSERT INTO @TEMPBIWEEKLYCENSUS 
     SELECT 
      [ProviderName], 
      AVG(ActiveClients), 
      CONVERT(VARCHAR(10), DATEPART(MONTH, @STARTDATE)) + '/' + CONVERT(VARCHAR(10), DATEPART(DAY, @STARTDATE)) + '-' + CONVERT(VARCHAR(10), DATEPART(MONTH, @CURRENTENDDATE)) + '/' + CONVERT(VARCHAR(10), DATEPART(DAY, @CURRENTENDDATE)) 
     FROM 
      [dbo].[DailyClientPopulation] 
     WHERE 
      CONVERT(DATE, DateAdded) >= @STARTDATE 
      AND CONVERT(DATE, DateAdded) <= @CURRENTENDDATE 
     GROUP BY 
      ProviderName 

    SET @STARTDATE = CONVERT(DATE,DATEADD(DAY,1,@CURRENTENDDATE)) 
END 

SELECT 
    ProviderName, ActiveClients, BiWeeklyRange 
FROM 
    @TEMPBIWEEKLYCENSUS 

あなたは、このwhileループを削除し、アプローチベースを設定するコードを変換する方法を提案してくださいでした。

+0

私はSQL Serverを使用していると仮定していますが、私は、日付関数は、範囲を隔週に数ヶ月を分割する方法を示すために一時テーブルにサンプルデータの数ヶ月を追加していますか?それ以降のバージョンでは日付/時刻機能が強化されています。 –

+1

また、15日目はいつも切れていますか?または、その月の日に基づいて移動しますか? 2月は14日ですか?乾杯。 –

+1

要件に応じて、開始および終了パラメータに基づく集計テーブルを使用して日付のテーブルを生成することができます。 – SMM

答えて

1

DateAddedの日付値を使用してBiWeeklyの開始日と終了日を生成し、where句のロジック間に含めると、dbo.DailyClientPopulationにいくつかのサブクエリをクロスすることができます。どのバージョン

-- insert sample data 
if object_id('tempdb..#DailyClientPopulation') is not null 
    drop table #DailyClientPopulation 
go 
create table #DailyClientPopulation 
    (
    Provider char(2), 
    Activeclients int, 
    DateAdded datetime 
    ) 
insert into #DailyClientPopulation 
    values 
     ('p1',10,'2016-11-01'), 
     ('p1',15,'2016-11-02'), 
     ('p2',14,'2016-11-01'), 
     ('p1',70,'2016-11-30'), 
     ('p2',50,'2016-11-30'), 
     ('p1',10,'2016-12-01'), 
     ('p1',15,'2016-12-02'), 
     ('p2',14,'2016-12-01'), 
     ('p1',70,'2016-12-30'), 
     ('p2',50,'2016-12-30'), 
     ('p1',10,'2017-01-01'), 
     ('p1',15,'2017-01-02'), 
     ('p2',14,'2017-01-01'), 
     ('p1',70,'2017-01-30'), 
     ('p2',50,'2017-01-30'), 
     ('p1',10,'2017-02-01'), 
     ('p1',15,'2017-02-02'), 
     ('p2',14,'2017-02-01'), 
     ('p1',70,'2017-02-28'), 
     ('p2',50,'2017-02-28') 

-- return AvgActiveClients per BiWeeklyRange 
select 
    dcp.Provider, 
    avg(dcp.ActiveClients) as AvgActiveClients, 
    convert(varchar(10),bed.begin_date,101) + ' - ' + convert(varchar(10),bed.end_date,101) as BiWeeklyRange 
from #DailyClientPopulation dcp 
    cross apply (values(dateadd(mm,datediff(mm,0,dcp.DateAdded),0))) bom(bom_date) -- begin of month 
    cross apply (values(dateadd(dd,-1,dateadd(mm,1,bom.bom_date)))) eom(eom_date) -- end of month 
    cross apply (values(dateadd(dd,day(eom.eom_date)/2,bom.bom_date))) bosh(bosh_date) -- begin of second half 
    cross apply (values(dateadd(dd,-1,bosh.bosh_date))) eofh(eofh_date) -- end of first half 
    cross apply (values(bom.bom_date,eofh.eofh_date), 
         (bosh.bosh_date,eom.eom_date)) bed(begin_date,end_date) -- begin/end dates 
where dcp.DateAdded between bed.begin_date and bed.end_date 
group by 
    dcp.Provider, 
    bed.begin_date, 
    bed.end_date 
order by 
    bed.begin_date, 
    dcp.Provider 
+1

ハードコードされた値の代わりに、月番号にlogivを使用できませんか? – Vinni

+0

私は提案された解決策を更新しました。これは、DateAdded月をBiWeeklyの日付範囲に分割するために、 'cross apply'といくつかの複雑な日付関数ロジックを使用します。 –

関連する問題