如何根据给定季度计算上一个和下一个季度?

时间:2018-07-18 07:28:55

标签: sql oracle oracle11g

当我传递当前季度值时,我想计算上一个和下一个季度。所以例如如果我通过“ Q3”或“ Q4”,

输出应为:

Current Quarter           Previous Quarter             Next Quarter
----------------------------------------------------------------------
     Q3                         Q2                         Q4
     Q4                         Q3                         Q1                          

Oracle中是否有可用的功能来实现相同的功能?

如何使用“选择查询”到达此输出?

3 个答案:

答案 0 :(得分:2)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE quarters ( value ) AS
  SELECT 'Q' || LEVEL FROM DUAL CONNECT BY LEVEL <= 4;

查询1 ,使用SUBSTRMOD计算下一个/上一个值:

SELECT value As current_q,
       'Q' || ( MOD( SUBSTR( value, 2 ), 4 ) + 1 ) AS next_q,
       'Q' || ( MOD( SUBSTR( value, 2 ) + 2, 4 ) + 1 ) AS prev_q
FROM   quarters

查询2 使用CASE来列举可能性:

SELECT value AS current_q,
       CASE value
       WHEN 'Q1' THEN 'Q2'
       WHEN 'Q2' THEN 'Q3'
       WHEN 'Q3' THEN 'Q4'
       WHEN 'Q4' THEN 'Q1'
       END As next_q,
       CASE value
       WHEN 'Q1' THEN 'Q4'
       WHEN 'Q2' THEN 'Q1'
       WHEN 'Q3' THEN 'Q2'
       WHEN 'Q4' THEN 'Q3'
       END As prev_q
FROM   quarters

查询3 ,使用DECODE列举可能性:

SELECT value AS current_q,
       DECODE( value, 'Q1', 'Q2', 'Q2', 'Q3', 'Q3', 'Q4', 'Q4', 'Q1' ) AS next_q,
       DECODE( value, 'Q1', 'Q4', 'Q2', 'Q1', 'Q3', 'Q2', 'Q4', 'Q3' ) AS prev_q
FROM   quarters

Results (针对所有查询):

| CURRENT_Q | NEXT_Q | PREV_Q |
|-----------|--------|--------|
|        Q1 |     Q2 |     Q4 |
|        Q2 |     Q3 |     Q1 |
|        Q3 |     Q4 |     Q2 |
|        Q4 |     Q1 |     Q3 |

答案 1 :(得分:2)

Oracle不允许您将四分之一转换为完整日期。

最简单的事情可能是对组合进行硬编码,因为只有这么少:

with t (current_quarter) as (
            select 'Q1' from dual
  union all select 'Q2' from dual
  union all select 'Q3' from dual
  union all select 'Q4' from dual
)
select current_quarter,
  case current_quarter
    when 'Q1' then 'Q4'
    when 'Q2' then 'Q1'
    when 'Q3' then 'Q2'
    when 'Q4' then 'Q3'
    else 'invalid'
  end as previous_quarter,
  case current_quarter
    when 'Q1' then 'Q2'
    when 'Q2' then 'Q3'
    when 'Q3' then 'Q4'
    when 'Q4' then 'Q1'
    else 'invalid'
  end as next_quarter
from t;

CU PREVIOU NEXT_QU
-- ------- -------
Q1 Q4      Q2     
Q2 Q1      Q3     
Q3 Q2      Q4     
Q4 Q3      Q1 

尽管如此,您可以通过数学方法来实现,方法是将数字部分拆分并进行调整:

with t (current_quarter) as (
            select 'Q1' from dual
  union all select 'Q2' from dual
  union all select 'Q3' from dual
  union all select 'Q4' from dual
)
select current_quarter,
  'Q' || (mod(to_number(substr(current_quarter, 2, 1)) + 2, 4) + 1) as previous_quarter,
  'Q' || (mod(to_number(substr(current_quarter, 2, 1)), 4) + 1) as next_quarter
from t;

CU PREVIOUS_QUARTER                          NEXT_QUARTER                             
-- ----------------------------------------- -----------------------------------------
Q1 Q4                                        Q2                                       
Q2 Q1                                        Q3                                       
Q3 Q2                                        Q4                                       
Q4 Q3                                        Q1                                       

可以(ab)使用日期操纵符,方法是分解数字四分之一数字并从标称日期偏移:

with t (current_quarter) as (
  select 'Q1' from dual
  union all select 'Q2' from dual
  union all select 'Q3' from dual
  union all select 'Q4' from dual
)
select current_quarter,
  to_char(add_months(date '2000-01-01',
    3 * (to_number(substr(current_quarter, 2, 1)) - 2)), '"Q"Q') as previous_quarter,
  to_char(add_months(date '2000-01-01',
    3 * to_number(substr(current_quarter, 2, 1))), '"Q"Q') as next_quarter
from t;

CU PR NE
-- -- --
Q1 Q4 Q2
Q2 Q1 Q3
Q3 Q2 Q4
Q4 Q3 Q1

但是这似乎变得不必要地复杂了...

答案 2 :(得分:0)

尝试一下

with tst as
(
  Select level as lvl from dual CONNECT BY Level < 5
)
Select 'Q'||lvl as current_quarter,
'Q'||case when lvl = 1 then 4 else lvl -  1 end as previous_quarter,
'Q'||case when lvl = 4 then 1 else lvl +  1 end as next_quarter
from tst