SQL项目状态管道查询

时间:2018-03-26 20:49:18

标签: sql sql-server

我正在使用一个数据库,其中包含一个历史表,显示项目何时进入下一个开发状态。这是一些示例数据。

dbo.history_table

| ProjectID | State | Timestamp               |
|         1 |     1 | 2018-03-22 10:38:27.000 |
|         1 |     2 | 2018-03-23 10:22:56.000 |
|         1 |     3 | 2018-03-24 12:18:32.000 |
|         2 |     1 | 2018-03-24 11:01:17.000 |
|         1 |     4 | 2018-03-25 10:32:41.000 |
|         2 |     4 | 2018-03-26 12:39:03.000 |

有很多州看起来像这样:

| State # | Description     | Notes
| State 1 | Planning        |
| State 2 | Pre-Production  |
| State 3 | Production      |
| State 4 | Post-Production |
| State 5 | Successful      | Terminal state
| State 6 | Unsuccessful    | Terminal state
| State 7 | Cancelled       | Terminal state

这些状态大致是顺序的,但并不完全,并非总是如此。例如,每个项目只能以三种终端状态之一结束。此外,尽管所有项目都在州1开始,但并非所有项目都在终止之前就已经达到了所有州。

我需要编写一个查看特定状态的查询,并显示这些记录移动到的下一个状态。我从这个查询中需要的数据看起来像这样:

报告:状态2管道

| Total:            | 100 |
| Moved to State 3: |  50 |
| Moved to State 4: |   0 |
| Moved to State 5: |  25 |
| Moved to State 6: |   0 |
| Moved to State 7: | 25  |

1 个答案:

答案 0 :(得分:1)

这会使用LEAD逻辑来查找下一行的状态,并使用GROUPING SETS来添加总计:

with cte as
 (
   select 
      State,
      lead(State) 
      over (partition by ProjectID 
            order by Timestamp) as nextState
   from myTable
 ) 
select 
   case when grouping(nextState) = 1 then 'Total' else nextState end, 
   count(*)
from cte
where State = 2
group by grouping sets ((nextState), ())
order by grouping(nextState) desc, nextState

但对于不存在下一个州的州,它不会返回一行。您需要将此选择左连接到描述现有状态的表。