sql: сводка по случайным периодам - PullRequest
1 голос
/ 19 октября 2011

У меня есть две таблицы:

первая (сумма):

  amountid      date         amount
    1         01.01.2011      100
    2         02.01.2011       50
    3         04.01.2011      200
    4         10.01.2011      20
    5         11.01.2011      5

вторая (период):

  periodid      date
     1          01.01.2011
     2          03.01.2011
     3          05.01.2011

Мне нужна первая таблица группы пораз из второй таблицы и сумма (сумма):

для этого примера ответ:

      01.01.2011    150
      03.01.2011    200  
      05.01.2011    25

, пожалуйста, помогите мне с SQL-запросом.

Ответы [ 4 ]

3 голосов
/ 19 октября 2011

Пример данных

declare @Amount table
(
  amountid int,
  [date] datetime,
  amount int
)

declare @Period table
(
  periodid int,
  [date] datetime
)

insert into @Amount
select 1, '20110101', 100 union all
select 2, '20110102', 50  union all
select 3, '20110104', 200 union all
select 4, '20110110', 20  union all
select 5, '20110111', 5

insert into @Period
select 1, '20110101' union all
select 2, '20110103' union all
select 3, '20110105'

Запрос

select P.StartDate,
       sum(A.amount) as amount
from (
      select P1.[date] as StartDate,
             coalesce((select min(P2.[date])
                       from @Period as P2
                       where P1.[date] < P2.[date]), '99991231') as endDate
      from @Period as P1
     ) as P      
  inner join @Amount as A
    on A.[date] >= P.StartDate and 
       A.[date] < P.EndDate
group by P.StartDate   
1 голос
/ 19 октября 2011

Запрос для вычисления конечных дат для периодов:

select P1.periodid, P1.date as startdate, min(P2.date) as enddate
    from period P1 
    left outer join period P2 on P2.date > P1.date
    group by P1.periodid, P1.date

результаты

PERIODID STARTDATE  ENDDATE
        1 2011-01-01 2011-01-03
        2 2011-01-03 2011-01-05
        3 2011-01-05 NULL

С помощью этого вы можете суммировать все суммы для всех периодов, как этот

select P.periodid, P.startdate, P.enddate, sum(A.amount) as sum
    from (
        select P1.periodid, P1.date as startdate, min(P2.date) as enddate
            from period P1 
            left outer join period P2 on P2.date > P1.date
            group by P1.periodid, P1.date
        ) P 
        left outer join amount A
            on A.date >= P.startdate and (P.enddate is null or A.date < P.enddate)
    group by P.periodid, P.startdate, P.enddate

результаты

PERIODID STARTDATE  ENDDATE    SUM
        1 2011-01-01 2011-01-03 150
        2 2011-01-03 2011-01-05 200
        3 2011-01-05 NULL        25
0 голосов
/ 19 октября 2011

Пока у меня есть эти sql-ы с другого форума:


 declare @t table
 ( amountid int,date smalldatetime,amount int)

 declare @p table (periodid int,date smalldatetime)

 Insert into  @t
   Select 1,'2011-01-01', 100
 union all
  Select 2,'2011-01-02', 50
 union all
  Select 3,'2011-01-04', 200
   union all
  Select 4,'2011-01-10', 20
  union all
  Select 5,'2011-01-11', 5

 Insert into @p
  Select 1, '2011-01-01'
   union all
  Select 2, '2011-01-03'
   union all
    Select 3, '2011-01-05'

Select p.date, sum(t.amount) from 
@P p
inner join
@t t on
    p.date <= t.Date
where
    not exists
        ( select top 1 1 from @p pp where pp.Date > p.Date and pp.Date < t.Date)
group by p.Date

, если я прав, это лучший план, когда я делаю "показать план выполнения" на моем сервере.

Я прав?

0 голосов
/ 19 октября 2011
create table #amount (
    amountid    int,
    [date]      datetime,
    amount      int
)

create table #period (
    periodid    int,
    [date]      datetime
)

delete from #amount
delete from #period

insert into #amount
values (1, {d '2011-01-01'}, 100),
    (2, {d '2011-01-02'}, 50),
    (3, {d '2011-01-04'}, 200),
    (4, {d '2011-01-10'}, 20),
    (5, {d '2011-01-11'}, 5)

insert into #period
values (1, {d '2011-01-01'}),
    (2, {d '2011-01-03'}),
    (3, {d '2011-01-05'})


select p.date, SUM(a.amount) as amount
from #period p inner join
    (
        select a.amountid, MAX(p.periodid) as periodid
        from #amount a inner join
            #period p on a.date >= p.date   
        group by a.amountid
    ) mp on p.periodid = mp.periodid inner join
    #amount a on mp.amountid = a.amountid
group by p.date

Конечно, было бы проще, если бы у вашей таблицы периодов была конечная дата.

...