我有一个包含列的表:MONTH
,YEAR
,PROJECT_ID
,STATUS
。
状态可以是:
我想知道在某个月内完成了多少个项目,即:
where STATUS changed from anything that is NOT C to C;
听起来很简单......!
当任何给定项目完成时,很容易找到:
SELECT TOP 1 MONTH,YEAR,PROJECT_ID FROM Table WHERE PROJECT_ID=9236 AND RAG='C'
ORDER BY YEAR ASC, MONTH ASC
但是考虑到year = 2011
和month = 8
(例如),我不知道如何找到当月第一次拥有status='C'
的项目数量。有什么想法吗?
编辑项目在完成后仍然包含status='C'
行,因此我无法计算Cs,因为这将返回已完成项目的数量这个和前几个月(因此按时间顺序排列并选择前1个)。
2010年10月至2011年1月的样本数据:
Month | Year | Project | Status
-------------------------------
10 | 2010 | A | G
11 | 2010 | A | C
12 | 2010 | A | C
1 | 2011 | A | C
10 | 2010 | B | R
11 | 2010 | B | R
12 | 2010 | B | R
1 | 2011 | B | R
10 | 2010 | C | G
11 | 2010 | C | G
12 | 2010 | C | G
1 | 2011 | C | C
10 | 2010 | D | A
11 | 2010 | D | C
12 | 2010 | D | C
1 | 2011 | D | C
^项目A和D于2010年11月完成。项目B在所示的四个月中的任何一个月内都没有改变。项目C于2011年1月完成。 {Month,Year,Project}是主键。
因此,输入和输出将是:
10/2010 => 0
11/2010 => 2 (because of A and D)
12/2010 => 0
1/2011 => 1 (because of C)
答案 0 :(得分:1)
SELECT
distinctMonths.month,
distinctMonths.year,
count(countProjects.project) as numChanges
FROM
(
SELECT DISTINCT
month, year
FROM
Table
) as distinctMonths -- need to get all months available, independent of the project status, in case there were not an complete ones during a given month
LEFT OUTER JOIN
(
SELECT
Month, Year, Project
FROM
Table
WHERE
status = 'C' AND
NOT EXISTS ( -- this will filter out our result set to only include the earliest instance of the given project's complete status
SELECT
1
FROM
Table t2
WHERE
t2.project = Table.project AND
t2.status = 'C' AND
( -- this will convert the date fragments into proper date values, that can be compared easily
cast(
cast(t2.year as varchar) + '-' + cast(t2.month as varchar) + '-1'
as datetime)
<
cast(
cast(table.year as varchar) + '-' + cast(table.month as varchar) + '-1'
as datetime)
)
)
) as countProjects ON
distinctMonths.month = countProjects.month AND
distinctMonths.year = countProjects.year
GROUP BY
distinctMonths.month,
distinctMonths.year
ORDER BY
distinctMonths.year,
distinctMonths.month
答案 1 :(得分:1)
这将为您提供您正在寻找的计数
select p1.mm,p1.yyyy,COUNT(*)
from projs p1
join (select projid,MIN(yyyy*100+mm) as closedOn from projs
where stat='c' group by projId) xx
on xx.projId=p1.projId and p1.yyyy*100+p1.mm=xx.closedOn
where p1.stat='c'
group by p1.mm,p1.yyyy
内部查询确定项目关闭的日期,因此您将查找本月关闭的所有项目......
答案 2 :(得分:1)
你去了
WITH
src(month, year, project, status) AS (
SELECT 10,2010,'A','G' UNION ALL
SELECT 11,2010,'A','C' UNION ALL
SELECT 12,2010,'A','C' UNION ALL
SELECT 1,2011,'A','C' UNION ALL
SELECT 10,2010,'B','R' UNION ALL
SELECT 11,2010,'B','R' UNION ALL
SELECT 12,2010,'B','R' UNION ALL
SELECT 1,2011,'B','R' UNION ALL
SELECT 10,2010,'C','G' UNION ALL
SELECT 11,2010,'C','G' UNION ALL
SELECT 12,2010,'C','G' UNION ALL
SELECT 1,2011,'C','C' UNION ALL
SELECT 10,2010,'D','A' UNION ALL
SELECT 11,2010,'D','C' UNION ALL
SELECT 12,2010,'D','C' UNION ALL
SELECT 1,2011,'D','C'),
src_date (date, project, status) AS (
SELECT date = CONVERT(DATETIME, CONVERT(VARCHAR, year * 100 + month) + '01'), project, status
FROM src
)
SELECT month = CONVERT(VARCHAR, YEAR(alldates.date)) + '/' + CONVERT(VARCHAR, MONTH(alldates.date)),
projects = ISNULL(cnt.value,0)
FROM (
SELECT DISTINCT date
FROM src_date
) alldates
LEFT JOIN
(
SELECT date = min_date, value = COUNT(*)
FROM
(
SELECT project, min_date = MIN(date)
FROM src_date
WHERE status = 'C'
GROUP BY project
) mins
GROUP BY min_date
) cnt
ON alldates.date = cnt.date
答案 3 :(得分:1)
我喜欢使用这个函数:lead()over()。 例如,如果你有这个选择:
select Month, Year, Project, Status
from youTable
where 1 = 1 --if you have any condition
我使用lead()函数找到“status”列的下一个值,并将其与当前值进行比较:
select count(1) as number from
(select lead(Status) over(order by Project) as nextStatus, Month, Year, Project, Status
from youTable
where 1=1) as tmp
where tmp.nextStatus <> tmp.Status
现在,在数字I中,将“已更改”的值更改为“状态”列