Teradata SQL:来自同一查询中跨越年份的日期范围的组结果

时间:2018-01-30 18:29:01

标签: sql teradata

所以我有这个查询,它给出了在给定时间范围内每个月至少进行一次某种交易的账户数。在这种情况下,我会检查3个月内的交易。请参阅以下查询:

select  
  Yr
, count(distinct acct_nbr) as AcctCt

from  (
        select          
          Yr
        , acct_nbr
        , count(distinct Mth) as Mths        

        from  (
                select                  
                  extract(year from tran_dt) as Yr
                , acct_nbr        
                , extract(month from tran_dt) as Mth
                , tran_id

                from br.bdft

                where prod_type = 44
                and (tran_dt between '2017-10-01' and '2017-12-31'
                or tran_dt between '2016-10-01' and '2016-12-31'
                or tran_dt between '2015-10-01' and '2015-12-31'
                or tran_dt between '2014-10-01' and '2014-12-31'
                or tran_dt between '2013-10-01' and '2013-12-31')
                and tran_cd = 'DD'
              ) dt

        group by 1,2                
      ) dt2

where Mths = 3

group by 1

我得到的结果如下:

Yr:    AcctCt:
2017   258527
2016   231304
2015   188550
2014   210339
2013   170781

我目前按年度对结果进行分组,方法是从交易日期中提取年份。当日期范围跨越多年时(例如我在上面的查询中使用的内容),这样可以正常工作。但是,一旦我跨越了多年,例如2017-11-01至2018-01-31,这种方法不再有效。

是否有更好的方法可以将结果分组,无论我使用的日期范围如何,它总是有效?

3 个答案:

答案 0 :(得分:2)

创建第二个表以保存时间段(重度伪代码:将表time_periods创建为ID,period_name,start_date,end_date)。加入此表

new T[C]

按period_name列分组。

抱歉,时间紧迫,或者我会提供更多信息......但是概念就在这里(在表中定义时间段并使用之间连接到该表)。尝试一下,如果您仍然需要

,我会在今天/明天再次访问完整的解决方案

答案 1 :(得分:1)

当他们跨越多年时,只需减去一定的时间。对于您的示例,请将此表达式用于Yr

extract(year from add_months(tran_dt, -1) ) as Yr

答案 2 :(得分:1)

在提取年份之前,只需使用ADD_MONTHS调整日期即可。此外,不需要两个COUNT(DISTINCT)。

这是您简化的查询:

select          
  Yr
, count(*) as AcctCt      

from  (
        select                  
          Extract(YEAR From Add_Months(tran_dt,-1)) as Yr
        , acct_nbr        

        from br.bdft

        where prod_type = 44
        and (tran_dt between '2017-11-01' and '2018-01-31'
          or tran_dt between '2016-11-01' and '2017-01-31'
          or tran_dt between '2015-11-01' and '2016-01-31'
          or tran_dt between '2014-11-01' and '2015-01-31'
          or tran_dt between '2013-11-01' and '2014-01-31')
        and tran_cd = 'DD'
        group by acct_nbr
        , yr
        having count(distinct extract(month from tran_dt)) = 3
      ) dt
 group by 1

编辑:

要获得基于今天的三个月范围,您可以在CURRENT_DATE应用TRUNC / LAST_DAY / ADD_MONTHS计算。

select          
  Yr
, count(*) as AcctCt      

from  (
        select 
          -- shift back the date between 0 and 2 months based on the month of the current quarter
          -- to get the same year for consecutive months
          Extract(YEAR From Add_Months(tran_dt, -Extract(MONTH From currdt) MOD 3)) as Yr
        , acct_nbr        

        from br.bdft

        where prod_type = 44
        -- get the current months plus the two previous for the current and the previous four years
        -- will be calculated once = Explain shows hard-coded dates
        AND (   tran_dt BETWEEN Trunc(Add_Months(Current_Date,-2      ), 'mon') AND Last_Day(           Current_Date       ) 
             OR tran_dt BETWEEN Trunc(Add_Months(Current_Date,-2 -1*12), 'mon') AND Last_Day(Add_Months(Current_Date,-1*12))
             OR tran_dt BETWEEN Trunc(Add_Months(Current_Date,-2 -2*12), 'mon') AND Last_Day(Add_Months(Current_Date,-2*12))
             OR tran_dt BETWEEN Trunc(Add_Months(Current_Date,-2 -3*12), 'mon') AND Last_Day(Add_Months(Current_Date,-3*12))
             OR tran_dt BETWEEN Trunc(Add_Months(Current_Date,-2 -4*12), 'mon') AND Last_Day(Add_Months(Current_Date,-4*12))
            )
        and tran_cd = 'DD'
        group by acct_nbr
        , yr
        having count(distinct extract(month from tran_dt)) = 3
      ) dt
 group by 1 as Yr