我有以下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个月中打开的服务数量。
我希望这是有道理的,如果没有的话,对不起,请随时提出问题,我会尽力澄清。
输出需要看起来像当前输出表,但是当前仅显示该月内启动了多少服务,这不是我们想要的。
日期表是具有不同日期格式等的参考表。可以根据需要使用或添加该表。
答案 0 :(得分:1)
我不得不对您的数据做出一些假设。希望我稍后显示的查询可以让您轻松调整以下任何一项:
start_dttm
是datetime
或datetime2
列。end_dttm
的相应列,它提供了服务的结束日期/时间,并且该列中的null表示服务尚未结束。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 > 0
从WHERE
子句移到了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