【问题标题】:counting most recent consecutive rows with like data using tabibitosan使用 tabibitosan 计算具有相似数据的最近连续行
【发布时间】:2018-11-04 01:11:57
【问题描述】:

我的项目使用的是 Oracle SQL 数据库。我有一个历史表,它每周都会附加任务状态,并且正在尝试查询当前偏离轨道的任务偏离轨道的周数。这是我的源历史表的示例摘录:

ID  WEEK    ON_TRACK
1   1   N
1   2   Y
1   3   N
1   4   N
1   5   N
2   1   N
2   2   N
2   3   Y
2   4   Y
2   5   N
3   1   N
3   2   N
3   3   Y
3   4   Y
3   5   Y

我希望从最新的追加开始向后返回 ON_TRACK 中连续“N”值的计数。对于上面的示例数据,我希望查询返回:

ID  WKS_OFF_TRACK
1   3
2   1
3   0

我已经进行了一些研究,看起来 Tabibitosan 方法是最合乎逻辑的方法,并且我找到了充足的示例来给出符合 1 个标准的最大连续值,但我无法调整以返回符合 2 个条件(ID 和 ON_TRACK)的最新连续值。

这是我目前所拥有的

--this step creates a temp table with unique IDs for each weekly append to the historical table, and a 1 (if ON_TRACK = N) or 0 (if ON_TRACK = Y). This results in the expected info.
WITH HIST_TBL AS (
    SELECT DISTINCT(ID),
    CASE ON_TRACK
        WHEN 'N' THEN 1
        ELSE 0
        END AS OFF_TRACK,
    WEEK 
    FROM SOURCE_HISTORICAL_TBL
    ORDER BY ID,WEEK DESC)
-- end of temp table 

--this is where Im struggling I want one line per project number, and the sum of the latest string of 1s (weeks the task has been off track), until a 0 is reached.
SELECT ID,
       SUM(OFF_TRACK) AS WKS_OFF_TRACK
FROM   (SELECT WEEK,
               ID,
               OFF_TRACK,
               ROW_NUMBER() OVER (ORDER BY WEEK DESC) - ROW_NUMBER() OVER 
(PARTITION BY ID,OFF_TRACK ORDER BY WEEK DESC) GRP
        FROM   HIST_TBL)
GROUP BY ID, GRP
ORDER BY ID;

此代码导致每个项目偏离轨道的所有周的累积总和,对于我的示例数据,这将是:

ID  WKS_OFF_TRACK
1   4
2   3
3   2

任何想法我哪里出错了?

【问题讨论】:

    标签: sql oracle group-by count partition


    【解决方案1】:

    这是一种假设人们在某个时间点“走上正轨”的方法:

    select sht.id, count(*)
    from SOURCE_HISTORICAL_TBL sht
    where sht.week > (select max(sht2.week)
                      from SOURCE_HISTORICAL_TBL sht2
                      where sht2.id = sht.id and sht2.on_track = 'Y'
                    )
    group by sht.id;
    

    否则,还需要一个条件:

    select sht.id, count(*)
    from SOURCE_HISTORICAL_TBL sht
    where sht.week > (select max(sht2.week)
                      from SOURCE_HISTORICAL_TBL sht2
                      where sht2.id = sht.id and sht2.on_track = 'Y'
                     ) or
          not exists (select 1
                      from SOURCE_HISTORICAL_TBL sht2
                      where sht2.id = sht.id and sht2.on_track = 'Y'
                     )
    group by sht.id;
    

    您也可以将这些表述为分析函数:

    select id,
           sum(case when week > max_week_y or max_week_y is null then 1 else 0 end) as max_off_track
    from (select sht.*,
                 max(case when on_track = 'Y' then week end) over (partition by id) as max_week_y
          from SOURCE_HISTORICAL_TBL sht
         ) sht
    group by id;
    

    请注意,此版本将返回 0s 以供当前处于正轨的人使用。

    【讨论】:

      【解决方案2】:

      您可以在单个表扫描中完成:

      SQL Fiddle

      Oracle 11g R2 架构设置

      CREATE TABLE SOURCE_HISTORICAL_TBL ( ID, WEEK, ON_TRACK ) AS
      SELECT 1, 1, 'N' FROM DUAL UNION ALL
      SELECT 1, 2, 'Y' FROM DUAL UNION ALL
      SELECT 1, 3, 'N' FROM DUAL UNION ALL
      SELECT 1, 4, 'N' FROM DUAL UNION ALL
      SELECT 1, 5, 'N' FROM DUAL UNION ALL
      SELECT 2, 1, 'N' FROM DUAL UNION ALL
      SELECT 2, 2, 'N' FROM DUAL UNION ALL
      SELECT 2, 3, 'Y' FROM DUAL UNION ALL
      SELECT 2, 4, 'Y' FROM DUAL UNION ALL
      SELECT 2, 5, 'N' FROM DUAL UNION ALL
      SELECT 3, 1, 'N' FROM DUAL UNION ALL
      SELECT 3, 2, 'N' FROM DUAL UNION ALL
      SELECT 3, 3, 'Y' FROM DUAL UNION ALL
      SELECT 3, 4, 'Y' FROM DUAL UNION ALL
      SELECT 3, 5, 'Y' FROM DUAL UNION ALL
      SELECT 4, 1, 'N' FROM DUAL UNION ALL
      SELECT 5, 1, 'Y' FROM DUAL;
      

      查询 1

      SELECT ID,
             GREATEST(
               COALESCE( MAX( CASE ON_TRACK WHEN 'N' THEN WEEK END ), 0 )
               - COALESCE( MAX( CASE ON_TRACK WHEN 'Y' THEN WEEK END ), 0 ),
               0
             ) AS weeks
      FROM   SOURCE_HISTORICAL_TBL
      GROUP BY id
      ORDER BY id
      

      Results

      | ID | WEEKS |
      |----|-------|
      |  1 |     3 |
      |  2 |     1 |
      |  3 |     0 |
      |  4 |     1 |
      |  5 |     0 |
      

      【讨论】:

      • 谢谢!这也有效!看起来我有选择!
      猜你喜欢
      • 2020-05-28
      • 2014-04-21
      • 1970-01-01
      • 2012-11-13
      • 2018-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      相关资源
      最近更新 更多