Teradata SQL:确定有多少帐户在给定月份有状态更改

Teradata SQL: Determine how many accounts had status change in given month

好的,所以我有一个看起来像这样的 table:

Acct_id   Eff_dt      Expr_dt      Prod_cd   Open_dt
-------------------------------------------------------
111       2012-05-01  2013-06-01   A         2012-05-01
111       2013-06-02  2014-03-08   A         2012-05-01
111       2014-03-09  9999-12-31   B         2012-05-01
222       2015-07-15  2015-11-11   A         2015-07-15
222       2015-11-12  2016-08-08   B         2015-07-15
222       2016-08-09  9999-12-31   A         2015-07-15
333       2016-01-01  2016-04-15   B         2016-01-01
333       2016-04-16  2016-08-08   B         2016-01-01
333       2016-08-09  9999-12-31   A         2016-01-01
444       2017-02-03  2017-05-15   A         2017-02-03
444       2017-05-16  2017-12-02   A         2017-02-03
444       2017-12-03  9999-12-31   B         2017-02-03
555       2017-12-12  9999-12-31   B         2017-12-12

还有很多列我没有包括在内,因为它们在其他方面不相关。

我要确定的是有多少帐户在给定月份的 Prod_cd 中发生了变化,但仅在一个方向上发生了变化(因此在本例中从 A > B)。然而,有时一个帐户首先以 B 开户,然后更改为 A。或者它以 A 开户,更改为 B,然后又移回 A。我只想知道当前的一组帐户在给定月份的哪个位置Prod_cd 从 A 更改为 B。

Eff_dt 是对帐户进行更改的日期(可以是任何更改,例如地址更改、名称更改或我正在查找的产品代码更改)。

Expr_dt 是该行的到期日期,基本上是进行新更改之前的最后一天。当该行的日期为 9999-12-31 时,这是最新的行。

Open_dt 是帐户的创建日期。

我最初创建的查询是这样的:

select
   count(distinct acct_id)

from table

where prod_cd = 'B'
and expr_dt = '9999-12-31'
and eff_dt between '2017-12-01' and '2017-12-31'
and open_dt < '2017-12-01'

但它给我的结果看起来不对。我想专门跟踪发生的转化次数,但我得到的帐户数似乎太高了。

可能有一种方法可以使用 window 函数创建更可靠的查询,但考虑到 Prod_cd 更改可能发生在多个方向,我不确定如何编写该查询.如有任何帮助,我们将不胜感激!

如果您专门寻找开关A --> B,那么最简单的方法就是使用lag()。但是,Teradata 需要稍微不同的公式:

select count(distinct acct_id)
from (select t.*,
             max(prod_cd) over (partition by acct_id order by effdt rows between 1 preceding and 1 preceding) as prev_prod_cd
      from t
     ) t
where prod_cd = 'B' and prev_prod_cd = 'A' and
      expr_dt = '9999-12-31' and
      eff_dt between '2017-12-01' and '2017-12-31' and
      open_dt < '2017-12-01';

我猜测日期条件出现在外部查询中——这意味着它们 lag() 不使用它们。

类似于 Gordon 的回答,但使用受支持的 window 函数(而不是 LAG)并使用 Teradata 的 QUALIFY 子句进行滞后查找:

SELECT DISTINCT acct_id
FROM mytable    
QUALIFY 
    MAX(prod_cd) OVER (PARTITION BY acct_id ORDER BY eff_dt ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) = 'A'
    AND prod_cd = 'B'
    AND expr_dt = '9999-12-31'
    AND eff_dt between DATE '2013-01-01' and DATE '2017-12-31'
    AND open_dt < DATE '2017-12-01'