我有下表:
+-------------+---------------------+---------------------+
| status | open_time | close_time |
+-------------+---------------------+---------------------+
| closed | 01-11-2014 19:32:44 | 01-11-2014 20:32:44 |
| open | 01-12-2014 22:33:49 | 02-12-2014 22:33:49 |
| open | 01-23-2014 22:08:24 | 03-23-2014 22:08:24 |
| closed | 02-01-2014 22:33:57 | 03-01-2014 22:33:57 |
| open | 02-01-2013 22:37:34 | 02-01-2013 23:37:34 |
| closed | 04-20-2013 15:23:00 | 05-20-2013 15:23:00 |
| open | 04-20-2013 12:21:49 | 05-20-2013 12:21:49 |
| closed | 04-25-2013 11:22:00 | 06-25-2013 11:22:00 |
| closed | 05-20-2013 14:23:49 | 10-20-2013 14:23:49 |
| closed | 04-20-2013 16:33:49 | 04-25-2013 16:33:49 |
+-------------+---------------------+---------------------*
我想展示这个结果:
+-------------+---------------+--------------+---------+
| Year | Month | Opened Cases | Closed Cases | Backlog |
+-------------+---------------+--------------+---------+
| 2014 | 4 | 10 | 5 | 62 | (57 + 5)
| 2014 | 3 | 9 | 7 | 57 | (52 + 2)
| 2014 | 2 | 15 | 20 | 52 | (57 - 5)
| 2014 | 1 | 12 | 1 | 57 | (46 + 11)
| 2013 | 12 | 10 | 9 | 46 | (45 + 1)
| 2013 | 11 | 50 | 5 | 45 | (45)
+--------------+--------------+--------------+---------+
其实我面临两种情况:
情况#1:我无法为已结案例获得正确的价值。试图在没有运气的地方使用条款。
情况#2:在关闭已关闭的案例后,我应该做(已打开 - 已关闭)并在几个月内累积,因此这将是积压案件。
如果我执行以下操作,请选择:
SELECT
YEAR(open_time) AS Ano,
MONTH(open_time) AS Mes,
sum(CASE WHEN DATEPART(YYYY, open_time)= 2013 AND DATEPART(MM, open_time)= 11 THEN 1 ELSE 0 END) Abertos,
sum(CASE WHEN DATEPART(YYYY, close_time)= 2013 AND DATEPART(MM, close_time)= 11 THEN 1 ELSE 0 END) Fechados
FROM
TABLE
WHERE
GROUPDESC= 'SUPPORT'
GROUP BY
MONTH(open_time),
YEAR(open_time)
ORDER BY
Ano DESC,
Mes DESC
我得到(这是关闭案例的正确值):
+-------------+---------------+--------------+
| Year | Month | Opened Cases | Closed Cases |
+-------------+---------------+--------------+
| 2014 | 4 | 0 | 0 |
| 2014 | 3 | 0 | 0 |
| 2014 | 2 | 0 | 0 |
| 2014 | 1 | 0 | 0 |
| 2013 | 12 | 0 | 0 |
| 2013 | 11 | 50 | 5 |
+--------------+--------------+--------------+
但如果我这样做:
SELECT
YEAR(open_time) AS Ano,
MONTH(open_time) AS Mes,
sum(CASE WHEN DATEPART(YYYY, open_time)= YEAR(open_time) AND DATEPART(MM, open_time)= MONTH(open_time) THEN 1 ELSE 0 END) Abertos,
sum(CASE WHEN DATEPART(YYYY, close_time)= YEAR(close_time) AND DATEPART(MM, close_time)= YEAR(close_time) THEN 1 ELSE 0 END) Fechados
FROM
TABLE
WHERE
GROUPDESC= 'SUPPORT'
GROUP BY
MONTH(open_time),
YEAR(open_time)
ORDER BY
Ano DESC,
Mes DESC
我明白了:
+-------------+---------------+--------------+
| Year | Month | Opened Cases | Closed Cases |
+-------------+---------------+--------------+
| 2014 | 4 | 0 | 0 |
| 2014 | 3 | 0 | 0 |
| 2014 | 2 | 0 | 0 |
| 2014 | 1 | 0 | 0 |
| 2013 | 12 | 0 | 0 |
| 2013 | 11 | 50 | 50 |
+--------------+--------------+--------------+
答案 0 :(得分:1)
以下是解决问题的一种方法:选择每月的所有开仓数和每月的所有结算数。然后全外连接它们。累积是一个所谓的运行总计,你可以使用SUM OVER。
select
coalesce(opened.ano, closed.ano) as ano,
coalesce(opened.mes, closed.mes) as mes,
coalesce(opened.cnt, 0) as opened_cases,
coalesce(closed.cnt, 0) as closed_cases,
sum(coalesce(opened.cnt, 0) - coalesce(closed.cnt, 0)) over (order by coalesce(opened.ano, closed.ano), coalesce(opened.mes, closed.mes)) as backlog
from
(
select
year(open_time) as ano,
month(open_time) as mes,
count(*) as cnt
from probsummarym1
where groupdesc = 'SUPPORT'
group by year(open_time), month(open_time)
) opened
full outer join
(
select
year(close_time) as ano,
month(close_time) as mes,
count(*) as cnt
from probsummarym1
where groupdesc = 'SUPPORT'
and status = 'closed'
group by year(close_time), month(close_time)
) closed
on opened.ano = closed.ano and opened.mes = closed.mes
order by coalesce(opened.ano, closed.ano) desc, coalesce(opened.mes, closed.mes) desc;
这是SQL小提琴:http://sqlfiddle.com/#!6/68dcf/7。
另一种方法是使用UNION ALL粘合开始事件和关闭事件,然后计数:
select
ano,
mes,
opened_cases,
closed_cases,
sum(opened_cases - closed_cases) over (order by ano, mes) as backlog
from
(
select
year(fecha) as ano,
month(fecha) as mes,
sum(case when evento = 'opened' then 1 else 0 end) as opened_cases,
sum(case when evento = 'closed' then 1 else 0 end) as closed_cases
from
(
select 'opened' as evento, open_time as fecha
from probsummarym1
where groupdesc = 'SUPPORT'
union all
select 'closed' as evento, close_time as fecha
from probsummarym1
where groupdesc = 'SUPPORT'
and status = 'closed'
) x
group by year(fecha), month(fecha)
) y
order by ano desc, mes desc;
这是第二个SQL小提琴:http://sqlfiddle.com/#!6/68dcf/18。
编辑:没有SUM?这太糟糕了。所以你必须再次选择计数。这很慢,因为必须每个月再次扫描一次表。
对于每个月,我们必须找到所有开始日期,直到那时为止所有结束日期。由于在开始之前永远不会发生结束,我们可以选择开始日期匹配的所有记录并计算这些记录。在这些记录中,我们还将找到所有可能的结束日期。我们统计这些(用和和案例),减去,我们就完成了。
所以你必须更换SUM() OVER as backlog
部分:
(
select
count(*)
-
sum
(
case
when eventsuntil.status = 'closed'
and year(eventsuntil.close_time) * 100 + month(eventsuntil.close_time) >=
y.ano * 100 + y.mes
then 1 else 0
end
)
from probsummarym1 eventsuntil
where eventsuntil.groupdesc = 'SUPPORT'
and year(eventsuntil.open_time) * 100 + month(eventsuntil.open_time) >=
y.ano * 100 + y.mes
) as backlog
但是,即使在2012版本中,SQL Server也无法执行此操作,我认为这是一个dbms漏洞。 y.ano和y.mes(或coalesce(opened.ano,closed.ano)和coalesce(opens.mes,closed.mes)的第一个语句)应被视为内部查询的常量,因为评估是按照每个外部记录,即月份,但它们不是。我不知道如何克服这个问题。也许SQL Server的一些专家可以帮助你。
以下是导致语法错误的两个小提琴:http://sqlfiddle.com/#!6/68dcf/32和http://sqlfiddle.com/#!6/68dcf/31。对不起,我不能再帮到你了。
答案 1 :(得分:0)
试试这个。
;with CTE as (
SELECT
row_number() over (partition by groupdesc order by YEAR(open_time), MONTH(open_time)) "Date_Order",
YEAR(open_time) "Year",
MONTH(open_time) "Month",
SUM(CASE status WHEN 'open' THEN 1 ELSE 0 END) "open_count",
SUM(CASE status WHEN 'closed' THEN 1 ELSE 0 END) "closed_count",
SUM(CASE status WHEN 'open' THEN 1 ELSE 0 END) - SUM(CASE status WHEN 'closed' THEN 1 ELSE 0 END) "monthly_change"
FROM PROBSUMMARYM1
WHERE groupdesc = 'SUPPORT'
GROUP BY groupdesc,
YEAR(open_time),
MONTH(open_time)
)
select c1.Date_Order,
c1.Year,
c1.Month,
c1.open_count,
c1.closed_count,
sum(c2.monthly_change) "Backlog"
from CTE c1
join CTE c2
on c2.Date_Order <= c1.Date_Order
group by c1.Date_Order,
c1.Year,
c1.Month,
c1.open_count,
c1.closed_count
order by c1.Year desc,
c1.Month desc;
partition by groupdesc
然后按groupdesc
进行分组并非绝对必要,但它演示了如何使用row_number()
同时运行一个查询来为多个执行相同的操作groupdesc
。
您可以使用SUM() OVER()
来逃避,但我对OVER()
条款没有经验。请参阅http://technet.microsoft.com/en-us/library/ms189461.aspx,特别是示例C。