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'
好的,所以我有一个看起来像这样的 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'