Teradata SQL:在同一查询中,从跨年的日期范围对结果进行分组

Teradata SQL:在同一查询中,从跨年的日期范围对结果进行分组,sql,teradata,Sql,Teradata,因此,我有一个查询,它给了我一个帐户计数,在给定的时间范围内,每个月至少有一次特定类型的交易。在这种情况下,我将在3个月内检查交易。请参阅下面的查询: select Yr , count(distinct acct_nbr) as AcctCt from ( select Yr , acct_nbr , count(distinct Mth) as Mths fr

因此,我有一个查询,它给了我一个帐户计数,在给定的时间范围内,每个月至少有一次特定类型的交易。在这种情况下,我将在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
我目前正在按年份对结果进行分组,方法是从事务日期中提取年份。如果then日期范围不跨年份(例如,我在上面的查询中使用的内容),则此方法可以正常工作。但一旦我跨年度,例如2017-11-01到2018-01-31,这种方法就不再有效


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

创建第二个表来保存时间段(重psuedo代码:创建表时间段作为ID、时间段名称、开始日期、结束日期)。加入这张桌子

from br.bdft 
inner join time_periods on bdft.tran_dt between start_date and end_date
按句点名称列分组


抱歉,时间太短了,否则我会提供更多信息……不过概念就在这里(在表中定义时间段并使用between连接到该表)。试一试,如果您仍然需要创建第二个表来保存时间段(重psuedo代码:创建表时间段作为ID、期间名称、开始日期、结束日期),我将使用完整的解决方案重新访问今天/明天。加入这张桌子

from br.bdft 
inner join time_periods on bdft.tran_dt between start_date and end_date
按句点名称列分组


抱歉,时间太短了,否则我会提供更多信息……不过概念就在这里(在表中定义时间段并使用between连接到该表)。试一试,我会用一个完整的解决方案重温今天/明天,如果你仍然需要

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

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

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

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

在提取年份之前,只需使用ADD_MONTHS调整日期。此外,不需要两个计数(不同)

这是您的查询:

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
编辑:

要获得基于今天的三个月范围,您可以在当前日期应用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

在提取年份之前,只需使用ADD_MONTHS调整日期。此外,不需要两个计数(不同)

这是您的查询:

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
编辑:

要获得基于今天的三个月范围,您可以在当前日期应用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


这些日期范围总是预先硬编码/知道的?它将每月运行一次。理想情况下,我希望实现自动化,这样我就不必每月手动更新日期范围,但我是SQL新手,还不知道如何做到这一点(如果可能的话)。确定三个月范围的规则是什么?当前加上前4个月的前两个月加上当前年?是的,当前月+2个前几个月,以及当前年+前4年。这些日期范围始终是硬编码/提前知道的?它将每月运行。理想情况下,我希望实现自动化,这样我就不必每月手动更新日期范围,但我是SQL新手,还不知道如何做到这一点(如果可能的话)。确定三个月范围的规则是什么?当前加上前4个月的前两个月加上本年?是的,本月加上前2个月,本年加上前4年。有没有一种方法可以将其分组,而不必按年度加上月份?每一次我都必须手动调整,我正试图让它尽可能自动化。是否有一种方法可以让所有的日期范围彼此分开,而我只需要指定一个日期?谢谢您的编辑。有没有一种简单的方法可以在Teradata中声明一个变量,在这里我可以输入一个日期,并计算该日期以外的所有其他范围?我预见了此报告的两个用例,一个是自动的,将在特定日期运行,另一个是我需要输入手动日期范围。因此,在您提供的编辑中,“Current_Date”将成为一个变量,所有其他逻辑保持不变。如果您不需要加入结果,可以将其包装在宏中:
将宏mymacro(currdt Date)替换为(SELECT…):
在宏中只需使用
:currdt
。您还可以在未提供参数/NULL时提供默认值。如果我确实需要将其连接到另一个表,您有什么建议?我没有在上面的查询中显示它,但我加入了另一个表,该表提取了所有帐户的计数,这样我就可以将查询结果与帐户总数进行比较,并计算出其中的百分比。Teradata只允许在宏或存储过程中使用参数。如果您总是需要将其连接到此特定表,请使用宏。否则,您可以在内部选择或应用我在这篇博文中描述的基于视图的参数,将日期作为currdt添加一次:有没有一种方法可以将其分组,而不必按年度和添加月份进行分组?每一次我都必须手动调整,我正试图让它尽可能自动化。是否有一种方法可以让所有的日期范围彼此分开,而我只需要指定一个日期?谢谢您的编辑。有没有一种简单的方法可以在Teradata中声明一个变量,在这里我可以输入一个日期,并计算该日期以外的所有其他范围?我预见了此报告的两个用例,一个是自动的,将在特定日期运行,另一个是我需要输入手动日期范围。因此,在您提供的编辑中,“Current_Date”将成为一个变量,所有其他逻辑保持不变。如果您不需要加入结果,可以将其包装在宏中:
将宏mymacro(currdt Date)替换为(SELECT…):
在宏中只需使用
:currdt
。如果未提供参数,也可以提供默认值/