【问题标题】:Teradata SQL: Group results from date ranges that cross years in same queryTeradata SQL:对同一查询中跨年份的日期范围的结果进行分组
【发布时间】:2018-07-09 17:43:27
【问题描述】:

所以我有这个查询,它可以让我计算在给定时间范围内每个月至少进行一次某种交易的帐户。在这种情况下,我正在检查 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

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

有没有更好的方法来对结果进行分组,无论我使用的日期范围如何,它始终有效?

【问题讨论】:

  • 那些日期范围总是硬编码/提前知道的?
  • 它将每月运行一次。理想情况下,我想自动化它,这样我就不必每个月手动更新日期范围,但我是一个 SQL 新手,还不知道该怎么做(如果可能的话)。
  • 您确定三个月范围的规则是什么?前 4 个月加上当前年份的当前加上前两个月份?
  • 是的,当月 + 前 2 个月,以及当年 + 前 4 年。

标签: sql teradata


【解决方案1】:

创建第二个表来保存时间段(大量伪代码:创建表 time_periods 作为 ID、period_name、start_date、end_date)。加入此表

from br.bdft 
inner join time_periods on bdft.tran_dt between start_date and end_date

按 period_name 列分组。

抱歉,时间紧迫,或者我会提供更多信息……但是这里有这个概念(在表格中定义时间段并使用 between 连接到该表格)。试一试,如果您仍然需要,我将在今天/明天重新访问完整的解决方案

【讨论】:

  • 嘿,我喜欢这个主意,因为我最后还加入了另一个表(上面的查询中没有显示),它会计算所有帐户,所以我可以计算一个百分比其中。我以前从未创建过临时表,所以现在正在研究它,但如果你有时间给出一个更好的例子,我将不胜感激。谢谢!
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    在提取年份之前,只需使用 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
    

    【讨论】:

    • 有没有办法不用 add_months 按年份进行分组?每次我都必须手动调整它,并且我试图尽可能地自动化。有没有办法让所有的日期范围相互抵消,而我只需要指定一个日期?
    • 感谢您的编辑。有没有一种简单的方法可以在 Teradata 中声明一个变量,我可以在其中输入一个日期,并计算该日期之外的所有其他范围?我预计此报告有两个用例,一个是自动化的,将在特定日期运行,另一个是我需要手动输入日期范围。因此,在您提供的编辑中,“Current_Date”将成为一个变量,而所有其他逻辑保持不变。
    • 如果您不需要加入结果,您可以将其包装在宏中:REPLACE MACRO mymacro (currdt DATE) AS (SELECT ....:): 在宏中只需使用:currdt。您还可以在未提供参数/NULL 时提供 DEFAULT。
    • 如果我确实需要将它加入另一个表,您有什么建议?我没有在上面的查询中显示它,但是我加入了另一个表,该表提取了所有帐户的计数,以便我可以将查询结果与帐户总数进行比较,并计算百分比那个。
    • Teradata 仅允许在宏或存储过程中使用参数。如果您总是需要将其加入到此特定表中,请使用宏。否则,您可以在内部 Select 中添加一次 DATE '...' as currdt 或应用我在这篇博文中描述的基于视图的参数:developer.teradata.com/blog/dnoeth/2011/03/…
    猜你喜欢
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 2012-05-15
    相关资源
    最近更新 更多