首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle SQL Trending MTD数据

Oracle SQL Trending MTD数据
EN

Stack Overflow用户
提问于 2016-09-28 17:43:50
回答 3查看 187关注 0票数 2

我正试图解决工作中的一个趋势问题,非常类似于下面的例子。我想我有一个方法,但不知道如何在SQL中实现它。

输入数据是:

代码语言:javascript
复制
MTD         LOC_ID  RAINED
1-Apr-16    1       Y
1-Apr-16    2       N
1-May-16    1       N
1-May-16    2       N
1-Jun-16    1       N
1-Jun-16    2       N
1-Jul-16    1       Y
1-Jul-16    2       N
1-Aug-16    1       N
1-Aug-16    2       Y

所需的输出是:

代码语言:javascript
复制
MTD         LOC_ID  RAINED  TRENDS
1-Apr-16    1       Y       New
1-May-16    1       N       No Rain
1-Jun-16    1       N       No Rain
1-Jul-16    1       Y       Carryover
1-Aug-16    1       N       No Rain
1-Apr-16    2       N       No Rain
1-May-16    2       N       No Rain
1-Jun-16    2       N       No Rain
1-Jul-16    2       N       No Rain
1-Aug-16    2       Y       New

我试图通过不依赖MTD的趋势从输入中产生输出。这样,当将新的月份添加到输入中时,输出就会发生变化,而无需编辑查询。

趋势的逻辑将出现在每一个独特的LOC_ID上。趋势将有三个值:第一个月下雨的“新”是"Y",接下来的几个月里“下雨”是"Y",“没有雨”在任何月份都是"N“。

我想通过引入一个带有listagg的中间步骤来自动化这个问题。例如,对于LOC_ID = "1":

代码语言:javascript
复制
MTD         LOC_ID  RAINED  PREV_RAINED
1-Apr-16    1       Y       (null) / 0 / (I don't care)
1-May-16    1       N       Y
1-Jun-16    1       N       Y;N
1-Jul-16    1       Y       Y;N;N
1-Aug-16    1       N       Y;N;N;Y

这样,在产出上产生“趋势”,我可以说:

代码语言:javascript
复制
case when RAINED = 'Y' then
    case when not regexp_like(PREV_RAINED, 'Y', 'i') then
        'New'
    else
        'Carryover'
    end
else
    'No Rain'
end as TRENDS

我的问题是,我不知道如何为每个唯一的PREV_RAINED生成LOC_ID,我觉得它需要按照MTD的LOC_ID顺序组合LOC_ID()语句和分区,但是我需要做的延迟的数量取决于每个月。

是否有一种简单的方法来生成PREV_RAINED,还是一个更简单的方法来解决我的整体问题,同时每个月保持自动化?

谢谢你阅读所有这些!:)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-28 18:57:17

在下面的SQL中有两个部分。

代码语言:javascript
复制
(i) Calculating the ROWNUMBER value for rained attribute at loc_id,rained level.
(ii) Get the count at partition level loc_id,rained.

通过计算上述两种情况,我们可以编写逻辑时根据您的需求计算趋势的情况。

代码语言:javascript
复制
SELECT mtd,
       loc_id,
       rained,
       CASE WHEN rained = 'N' THEN 'No Rain'
            WHEN rained = 'Y' AND rn = 1 THEN 'New'
            ELSE 'Carry Over'    
        END AS Trends       
  FROM
        ( 
            SELECT mtd,
                   loc_id,
                   rained,                   
                   ROW_NUMBER() OVER ( PARTITION BY loc_id,rained ORDER BY mtd ) AS rn,
                   COUNT(*) OVER ( PARTITION BY loc_id,rained ) AS count_locid_rained               
              FROM INPUT
              ORDER BY loc_id,mtd,rained,rn
         ) X;
票数 1
EN

Stack Overflow用户

发布于 2016-09-28 19:01:20

以下是旧版本的解决方案。WITH子句用于输入数据;解决方案在WITH子句之后立即开始。

接下来我将研究一个MATCH_RECOGNIZE解决方案,我可以将它添加到这个答案中。

代码语言:javascript
复制
with
     input_data ( mtd, loc_id, rained ) as (
       select to_date('1-Apr-16', 'dd-Mon-rr'), 1, 'Y' from dual union all
       select to_date('1-Apr-16', 'dd-Mon-rr'), 2, 'N' from dual union all
       select to_date('1-May-16', 'dd-Mon-rr'), 1, 'N' from dual union all
       select to_date('1-May-16', 'dd-Mon-rr'), 2, 'N' from dual union all
       select to_date('1-Jun-16', 'dd-Mon-rr'), 1, 'N' from dual union all
       select to_date('1-Jun-16', 'dd-Mon-rr'), 2, 'N' from dual union all
       select to_date('1-Jul-16', 'dd-Mon-rr'), 1, 'Y' from dual union all
       select to_date('1-Jul-16', 'dd-Mon-rr'), 2, 'N' from dual union all
       select to_date('1-Aug-16', 'dd-Mon-rr'), 1, 'N' from dual union all
       select to_date('1-Aug-16', 'dd-Mon-rr'), 2, 'Y' from dual
     )
select mtd, loc_id, rained,
       case rained when 'N' then 'No Rain'
                   else case when rn = 1 then 'New' 
                                         else 'Carryover' end
                   end  as trends
from ( select mtd, loc_id, rained, 
              row_number() over (partition by loc_id, rained order by mtd) rn
       from   input_data
)
order by loc_id, mtd
;

输出

代码语言:javascript
复制
MTD                     LOC_ID RAINED TRENDS  
------------------- ---------- ------ ---------
01/04/2016 00:00:00          1      Y New      
01/05/2016 00:00:00          1      N No Rain  
01/06/2016 00:00:00          1      N No Rain  
01/07/2016 00:00:00          1      Y Carryover
01/08/2016 00:00:00          1      N No Rain  
01/04/2016 00:00:00          2      N No Rain  
01/05/2016 00:00:00          2      N No Rain  
01/06/2016 00:00:00          2      N No Rain  
01/07/2016 00:00:00          2      N No Rain  
01/08/2016 00:00:00          2      Y New      

 10 rows selected
票数 1
EN

Stack Overflow用户

发布于 2016-09-28 21:46:50

使用MATCH_RECOGNIZE的解决方案(仅适用于Oracle12c)。在您的数据集中测试不同的解决方案;我被告知MATCH_RECOGNIZE可能比其他解决方案快得多,但这取决于许多因素。

代码语言:javascript
复制
select loc_id, mtd, rained, trends
from input_data
  match_recognize (
    partition by loc_id, rained
    order by     mtd
    measures     mtd as mtd,
                 case when rained = 'N' then 'No Rain'
                      else case when match_number() = 1 then 'New' else 'Carryover' end
                      end as trends
    pattern (a)
    define a as 0 = 0
  )
order by loc_id, mtd;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39754328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档