2016-11-30 3 views
3

У меня есть эта таблица, которая отображает поставщиков и активных активных клиентов в каждый день.Заменить цикл while на основе набора в SQL Server

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/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 

Не могли бы вы подсказать, как убрать это время цикла и преобразовывать код для установки на основе подхода.

+0

Я предполагаю, что вы используете SQL Server, но какую версию? Более поздние версии имеют улучшенные функции даты и времени, которые могут помочь. –

+1

Кроме того, это 15-й всегда отрезанный? Или он перемещается в зависимости от дней в месяце, например. для февраля это 14-й? Приветствия. –

+1

В зависимости от требований таблица дат может быть сгенерирована таблицей таблиц на основе начальных и конечных параметров. – SMM

ответ

1

Вы можете перекрещивать некоторые подзапросы с вашим dbo.DailyClientPopulation, используя значения даты DateAdded, чтобы создать даты начала и окончания BiWeekly, а затем включить между логикой в ​​предложении where. Я добавил несколько месяцев выборочных данных на временную таблицу, чтобы показать, как функция даты разделить месяцев в Biweekly диапазоны:

-- 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

Вместо жестко закодированных значений, нельзя ли использовать какой-либо логин для номера месяца? – Vinni

+0

Я обновил предлагаемое решение. В этом случае используется «cross apply» и некоторая сложная логика функций даты, чтобы разделить DateAdded months на диапазоны дат BiWeekly. –

Смежные вопросы