oracle sql计数值为几周,直到特定列更改为止

时间:2017-07-01 19:53:30

标签: sql oracle count distinct-values

我尝试计算特定任务的值,即使它们没有被更改。 我需要计算每周的状态,直到状态发生变化(然后必须计算新状态)。 我得到了下表作为基本值的结果。

SRQNR      KW   Status
TB-17-0002  1   Status 05
TB-17-0002  1   Status 20
TB-17-0002  1   Status 25
TB-17-0002  1   Status 30
TB-17-0002  8   Status 40
TB-17-0002  8   Status 44
TB-17-0002  8   Status 45
TB-17-0004  1   Status 05
TB-17-0004  1   Status 20
TB-17-0004  2   Status 25
TB-17-0004  2   Status 30
TB-17-0004  2   Status 40
TB-17-0004  2   Status 44
TB-17-0004  4   Status 70
TB-17-0004  4   Status 85
TB-17-0004  4   Status 90
TB-17-0005  1   Status 05
TB-17-0005  1   Status 20
TB-17-0005  1   Status 25
TB-17-0005  1   Status 30
TB-17-0005  2   Status 40
TB-17-0005  2   Status 44
TB-17-0005  6   Status 45
TB-17-0006  1   Status 05
TB-17-0006  1   Status 20
TB-17-0006  1   Status 25
TB-17-0006  1   Status 30
TB-17-0006  1   Status 40
TB-17-0006  11  Status 44
TB-17-0006  11  Status 45
TB-17-0007  1   Status 05
TB-17-0007  1   Status 20
TB-17-0007  1   Status 25
TB-17-0007  1   Status 30
TB-17-0007  2   Status 40
TB-17-0007  2   Status 44
TB-17-0007  2   Status 45
TB-17-0008  1   Status 05
TB-17-0008  1   Status 20
TB-17-0008  2   Status 25
TB-17-0008  2   Status 30
TB-17-0008  2   Status 40
TB-17-0008  2   Status 44
TB-17-0008  2   Status 45
TB-17-0009  1   Status 05
TB-17-0009  1   Status 20
TB-17-0009  1   Status 25
TB-17-0009  1   Status 30
TB-17-0009  1   Status 40
TB-17-0009  15  Status 44
TB-17-0009  15  Status 45
TB-17-0010  1   Status 05
TB-17-0010  1   Status 20
TB-17-0010  1   Status 25
TB-17-0010  1   Status 30
TB-17-0010  1   Status 40
TB-17-0010  1   Status 44
TB-17-0010  5   Status 45
TB-17-0011  1   Status 05
TB-17-0011  1   Status 20
TB-17-0011  1   Status 25
TB-17-0011  11  Status 30
TB-17-0011  11  Status 40
TB-17-0011  11  Status 44
TB-17-0011  11  Status 70
TB-17-0011  11  Status 85
TB-17-0011  20  Status 90

例如,srqnr TB-17-0002在KW 1中获得状态30,在KW8中变为状态40。 现在我的愿望是,对于KW 2,3,4,5,6,7状态30将被计算在内。

Interpretation

因为SRQNS在状态30中仍然是KW 3或4,这也应该在解释中。

感谢您的解决方案。

1 个答案:

答案 0 :(得分:0)

使用派生的范围集合作为行,并将KW作为一组列,这似乎需要按这些范围进行分组,然后按KW值进行旋转。根据给出的样本数据,得出了这个结果:

+----------+------+------+------+------+------+------+------+------+------+------+----+------+------+------+------+------+------+------+------+------+
|  RANGES  |  1   |  2   |  3   |  4   |  5   |  6   |  7   |  8   |  9   |  10  | 11 |  12  |  13  |  14  |  15  |  16  |  17  |  18  |  19  |  20  |
+----------+------+------+------+------+------+------+------+------+------+------+----+------+------+------+------+------+------+------+------+------+
| <=29     | 31   | 4    | null | null | null | null | null | null | null | null |  1 | null | null | null | null | null | null | null | null | null |
| 30 to 69 | 4    | 10   | null | null | 1    | 1    | null | 3    | null | null |  4 | null | null | null | 2    | null | null | null | null | null |
| 70 to 84 | null | null | null | 1    | null | null | null | null | null | null |  1 | null | null | null | null | null | null | null | null | null |
| 85 to 90 | null | null | null | 2    | null | null | null | null | null | null |  1 | null | null | null | null | null | null | null | null | 1    |
+----------+------+------+------+------+------+------+------+------+------+------+----+------+------+------+------+------+------+------+------+------+

使用此查询:

SELECT 
   * 
FROM (
        select
           case when substr(status,-2,2) < '30' then '<=29'
                when substr(status,-2,2) between '30' and '69' then '30 to 69'
                when substr(status,-2,2) between '70' and '84' then '70 to 84'
                when substr(status,-2,2) between '85' and '90' then '85 to 90'
                else '???'
                end as ranges
         , KW
         , count(*) as counter
        from mytable t
        group by
           case when substr(status,-2,2) <= '30' then '<=29'
                when substr(status,-2,2) between '30' and '69' then '30 to 69'
                when substr(status,-2,2) between '70' and '84' then '70 to 84'
                when substr(status,-2,2) between '85' and '90' then '85 to 90'
                else '???'
                end
         , KW
        )
PIVOT (
   SUM(counter) 
   FOR 
      (KW) 
   IN 
      (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
    )
;

注意我没有试过从Status到范围的子字符串处理。您可能更喜欢使用 IN(...),具体取决于该列中的实际数据。

dbfiddle here