前一个月的动态12个月滚动总计,回溯到12个月

时间:2018-07-27 09:45:58

标签: sql sql-server sql-server-2016

我有以下sql代码(where子句仅用于限制当前行)

select 
    month,
    monthname,
    year,
    count(distinct case when a.dim_service_type_id_desc like '%Direct Payment%' then a.DIM_PERSON_ID else null end) as No_dp,
    count(distinct a.DIM_PERSON_ID) as no_ppl
from   
    SERVICE_PROVISIONS a
    inner join date_tbl d on CONVERT(VARCHAR(35),a.start_dttm,112) = d.dim_date_id
where 
    a.dim_person_id >0
    and year = 2018
group by 
    month,
    monthname,
    year

我的输出是这个

month monthname     year    No_dp   no_ppl
1       January     2018    142     1604
2       February    2018    111     1526
3       March       2018    133     1636
4       April       2018    1107    3829
5       May         2018    140     1575
6       June        2018    131     1389
7       July        2018    200     893
8       August      2018    2       73
9       September   2018    1       32
10      October     2018    2       21
11      November    2018    2       21
12      December    2018    2       19

所以我的问题是-客户想要查看在过去的12个月中打开了多少服务(使用开始日期和结束日期)(不是启动了多少服务,而是当前没有结束的服务)。在使用当月时,这很好,但是他们希望在前12个月中也将其显示为滚动动态数字。

例如,在7月的这个月中,他们想查看在过去的12个月中打开了多少服务。六月的上个月,他们想查看在六月之前的12个月中打开了多少服务,以此类推,在过去的12个月中等等。

该表需要具有最近12个月的月份名称,并在列中显示该月之后的前12个月中打开的服务数量。

我希望这是有道理的,如果没有的话,对不起,请随时提出问题,我会尽力澄清。

输出需要看起来像当前输出表,但是当前仅显示该月内启动了多少服务,这不是我们想要的。

日期表是具有不同日期格式等的参考表。可以根据需要使用或添加该表。

2 个答案:

答案 0 :(得分:1)

我不得不对您的数据做出一些假设。希望我稍后显示的查询可以让您轻松调整以下任何一项:

  1. 我用它的名字猜测start_dttmdatetimedatetime2列。
  2. 我假设有一个名为end_dttm的相应列,它提供了服务的结束日期/时间,并且该列中的null表示服务尚未结束。
  3. 我对服务在给定月份内“开放”意味着什么的最好猜测是,该服务在该月内或该月之前的某个时间开始,直到该月结束时才结束。 li>
  4. 我从您的原始查询中假设,具有相同dim_person_id的多个服务并不代表不同的服务。

由于我不知道您的date_tbl中包含什么,因此我将显示一个不需要此示例的示例。考虑以下查询:

select
    BeginDate = dateadd(month, -1, dateadd(day, 1, eomonth(getdate(), -Offset.X))),
    EndDate = dateadd(day, 1, eomonth(getdate(), -Offset.X))
from
    (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)) Offset(X)

这将为您提供12条记录,分别代表当月和前11个月中的每个月。请注意,我在这里的EndDate实际上不是该月的最后一天,而是以下月的第一天。我这样做是因为上面的假设1;由于您的服务日期可能具有时间成分,因此,我将通过检查日期是否严格早于下个月的开始来确定它们是否属于给定月份。这是该查询给我的:

BeginDate   EndDate
2018-07-01  2018-08-01
2018-06-01  2018-07-01
2018-05-01  2018-06-01
2018-04-01  2018-05-01
2018-03-01  2018-04-01
2018-02-01  2018-03-01
2018-01-01  2018-02-01
2017-12-01  2018-01-01
2017-11-01  2017-12-01
2017-10-01  2017-11-01
2017-09-01  2017-10-01
2017-08-01  2017-09-01

现在,我将上述结果集添加到您的SERVICE_PROVISIONS数据中,在每个月中查找dim_person_id > 0(来自您的原始查询)且满足上述假设3的记录。

-- Some sample data (assumptions 1 & 2)
declare @SERVICE_PROVISIONS table (dim_person_id bigint, start_dttm datetime, end_dttm datetime);
insert @SERVICE_PROVISIONS values
    (1, '20180101', '20180315'),
    (1, '20180101', '20180315'),
    (2, '20171215', '20180520');

-- The CTE defines the months we'll report on, as described earlier.
with MonthsCTE as
(
    select
        BeginDate = dateadd(month, -1, dateadd(day, 1, eomonth(getdate(), -Offset.X))),
        EndDate = dateadd(day, 1, eomonth(getdate(), -Offset.X))
    from
        (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)) Offset(X)
)

-- This query matches the months from the CTE against the applicable services.
select
    [Month] = datepart(month, M.BeginDate),
    [MonthName] = datename(month, M.BeginDate),
    [Year] = datepart(year, M.BeginDate),
    ServicesOpen = count(distinct S.dim_person_id)   -- Assumption 4
from
    MonthsCTE M
    left join @SERVICE_PROVISIONS S on
        S.dim_person_id > 0 and
        S.start_dttm < M.EndDate and   -- Assumption 3
        (
            S.end_dttm >= M.EndDate or
            S.end_dttm is null   -- Assumption 2
        )
group by
    M.BeginDate,
    M.EndDate
order by
    M.BeginDate;

请注意,我将dim_person_id > 0WHERE子句移到了JOIN,以便即使在此期间没有打开任何服务,这12个月中的每一个仍将出现在结果集中那时。结果:

Month   MonthName   Year   ServicesOpen
8       August      2017   0
9       September   2017   0
10      October     2017   0
11      November    2017   0
12      December    2017   1
1       January     2018   2
2       February    2018   2
3       March       2018   1
4       April       2018   1
5       May         2018   0
6       June        2018   0
7       July        2018   0

答案 1 :(得分:0)

类似这样的东西-如果您可以编写查询以获取所需行数的值,则可以使用cross apply链接到该查询。计数在一个月之前具有未完成记录但在该月之前没有结束记录的记录似乎可行

SELECT IQ. *, OA.SERVICE_PROVISIONS FROM (select 
month,
monthname,
year,
a.dim_person_id dim_person_id,
count(distinct case when a.dim_service_type_id_desc like '%Direct Payment%' then a.DIM_PERSON_ID else null end) as No_dp,
count(distinct a.DIM_PERSON_ID) as no_ppl

from   
SERVICE_PROVISIONS a
inner join date_tbl d on CONVERT(VARCHAR(35),a.start_dttm,112) = d.dim_date_id

where 
a.dim_person_id >0
and year = 2018

group by 
month,
monthname,
year) IQ
CROSS APPLY 
(SELECT count(0) OpenThings FROM SERVICE_PROVISIONS SP1 WHERE 
                 (sp1.startdate < DATEFROMPARTS(IQ.year,iq.month,1) 
                AND 
                sp1.enddate is null or sp1.enddate > DATEFROMPARTS(IQ.year,iq.month,1)) and sp1.dim_person_id = iq.dim_person_id
) AS OA
相关问题