2013-08-09 7 views
1

Таблица с именем 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 

Мне нужно отобразить запросы на ежедневной основе, где объем суммируется день по счету для данного диапазона дат, как в июле месяце доклад, как ниже. Даты начала и даты окончания запросов объема должны быть обрезаны для данного отчета даты

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 

Я ищу способы, которые не связаны с циклами или курсорами. Я нашел Similar Question. Ответы там мне не помогли.

+0

От чего же 710 как объем для 10-го? –

+0

@DanBracuk, поскольку есть запрос объема для '670' учетной записи для 10-го числа с -350 в качестве тома – Ram

ответ

2

Я хотел бы использовать таблицу даты, такую, как

CREATE TABLE #Dates(
    DateId INT, 
    CalendarDate DATETIME) 

заполненного с датами для любого диапазона вам нужно. Я использую эту таблицу для присоединения к таблицам, таким как VolumeRequest, для получения запрошенного результата.

SELECT 
    v.AccountId, 
    d.CalendarDate, 
    SUM(v.DailyVolume) 
FROM 
    #Dates d INNER JOIN 
    VolumeRequest v ON 
     d.CalendarDate >= v.StartDate AND 
     d.CalendarDate <= v.EndDate 
group by 
    d.CalendarDate, 
    v.AccountId 

заполнить таблицу #dates, я использую что-то вроде этого:

declare @startdate datetime = '6/1/13', @enddate datetime = '7/31/13' 

create table #Dates(CalendarDate datetime) 

insert into #Dates(CalendarDate) 
select 
    dateadd(dd, rid-1, @startdate) as calendardate 
from (
    select 
     ROW_NUMBER() over(order by o.object_id) as rid 
    From 
     sys.objects o cross apply 
     sys.objects o2 
) dates 
where 
    dateadd(dd, rid-1, @startdate) >= @startdate and dateadd(dd, rid-1, @startdate) <= @enddate 

Modify для удовлетворения ваших потребностей диапазона дат.

+0

У меня нет прав на создание и выполнение. – Ram

+0

Можете ли вы создать временные таблицы? Если это так, вы должны использовать те же конструкции, что и выше, просто измените Даты на # Даты и заполните диапазон дат. – cgsmks

+0

Это создаст временную таблицу и заполнит датами с 6/1/13 до 7/31/13 и может быть изменена для любого диапазона дат, в котором вы нуждаетесь. – cgsmks

1

SQLFiddle demo

Использование С п и рекурсии мы генерируем Days таблицу со всеми дней между MIN и MAX дат. Затем создайте таблицу Accounts с отличным AccountID. Наконец, присоедините все эти таблицы и соберите все с 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) 
+0

Ваш код очень близок к тому, что мне нужно. Даты начала и окончания даты запросов объема должны быть обрезаны для данных дат отчета. В этом случае это месяц июля, поэтому записи в июне для '673' не должны существовать – Ram

+0

Ничего, что я изменил, это отвечает моим потребностям. Спасибо – Ram

+0

Если диапазон дат больше 100, я получаю ошибку 'Максимальная рекурсия 100 была исчерпана до завершения инструкции.' – Ram

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