SQL: 计算过去 3 个月中每个月都有特定交易 ID 的账户

SQL: count accounts with certain transaction ID present in each of past 3 months

我有一个 SQL 脚本,用于计算给定月份内具有特定交易 ID 的帐户数量。我想对此进行修改,以便它仅在过去 3 个月的每一个月(而不是任何给定月份)中放置这些类型的交易时才计算帐户数。这是为了过滤掉一次性事件。

我是 SQL 的新手,无法通过搜索找到明确的答案。将不胜感激任何帮助。谢谢!

SELECT
   CLDR.YEAR_MONTH
  ,COUNT(DISTINCT TRAN.ACCT_NBR) AS IC_DD --counts all unique Acct numbers

FROM
   REPORTS.FINANCIAL_TRAN AS TRAN

INNER JOIN REPORTS.ACCT AS ACCT ON TRAN.ACCT_NBR=ACCT.ACCT_NBR
INNER JOIN REPORTS.DATE AS CLDR ON TRAN.TRAN_DT=CLDR.CALENDAR_DATE

WHERE
   TRAN.TRAN_CD IN ('id1','id2','id3')  --Filters on Transaction IDs
 AND
   TRAN.TRAN_DT BETWEEN '2017-01-01' AND '2017-03-31'

GROUP BY
   CLDR.YEAR_MONTH

ORDER BY
   CLDR.YEAR_MONTH

一种蛮力方法是为每个月添加一个 IN 子句:

AND TRAN.ACCT_NBR IN (
       SELECT ACCT_NBR 
       FROM REPORTS.FINANCIAL_TRAN 
       WHERE TRAN_DT BETWEEN '2017-01-01' AND '2017-01-31')
AND TRAN.ACCT_NBR IN (
       SELECT ACCT_NBR 
       FROM REPORTS.FINANCIAL_TRAN 
       WHERE TRAN_DT BETWEEN '2017-02-01' AND '2017-02-28')
AND TRAN.ACCT_NBR IN (
       SELECT ACCT_NBR 
       FROM REPORTS.FINANCIAL_TRAN 
       WHERE TRAN_DT BETWEEN '2017-03-01' AND '2017-03-31')

这是我在 MSSQL 中的做法。我很确定您在 Teradata 中有 windowing 函数。

我正在为我的测试示例简化您的数据,但这应该能让您走上正轨。 CTE 的原因是您不能在 window 函数中使用 COUNT DISTINCT。

CREATE TABLE #Test (
     ACCT_NBR int
    ,YEAR_MONTH char(5)
    ,TRAN_DT datetime )

INSERT INTO #Test
SELECT 123, '17/01', '2017-01-11';
INSERT INTO #Test
SELECT 123, '17/02', '2017-02-12';
INSERT INTO #Test
SELECT 123, '17/02', '2017-02-21';
INSERT INTO #Test
SELECT 123, '17/03', '2017-03-19';
INSERT INTO #Test
SELECT 356, '17/01', '2017-01-14';
INSERT INTO #Test
SELECT 356, '17/01', '2017-01-22';
INSERT INTO #Test
SELECT 356, '17/03', '2017-03-14';

SELECT * FROM #Test;

WITH CTE AS (
    SELECT DISTINCT
         ACCT_NBR AS AccountNumber
        ,YEAR_MONTH AS YYMM
    FROM #Test
    WHERE TRAN_DT BETWEEN '2017-01-01' AND '2017-03-31' )

SELECT DISTINCT
     YYMM
    ,COUNT(AccountNumber) OVER (PARTITION BY YYMM ) AS Counts
FROM CTE

您不需要同时加入 ACCT 和日历 table:

SELECT Count(*)
FROM
 (
   SELECT ACCT_NBR
   FROM REPORTS.FINANCIAL_TRAN AS TRAN
   WHERE
      TRAN.TRAN_CD IN ('id1','id2','id3')  --Filters on Transaction IDs
    AND
      TRAN.TRAN_DT BETWEEN '2017-01-01' AND '2017-03-31'
   GROUP BY ACCT_NBR
   -- rows for all three months exist for this account 
   HAVING Count(DISTINCT EXTRACT(MONTH FROM tran_dt)) = 3
 ) AS dt

编辑:

根据评论,不应在固定的月份范围内执行此操作,而应动态执行,即每个月计算有多少帐户在前两个月内也有交易?

SELECT trans_month, Count(*)
FROM
 (
   SELECT
      ACCT_NBR,
     ,Trunc(TRAN_DT, 'mon') AS trans_month -- 1st of month
   FROM TRAN
   WHERE
      TRAN.TRAN_CD IN ('id1','id2','id3')  --Filters on Transaction IDs
--    AND
--      TRAN.TRAN_DT BETWEEN '2017-01-01' AND '2017-03-31'
   GROUP BY ACCT_NBR, trans_month -- distinct list first
   QUALIFY 
      -- check if there are three consecutive months
      -- e.g. 
      -- 2017-02-01 <- 2 preceding, must be 2 months before current row
      -- 2017-03-01 <- 1 preceding
      -- 2017-04-01 <- current row
      Min(trans_month)
      Over (PARTITION BY ACCT_NBR
            ORDER BY trans_month
            ROWS 2 Preceding) = Add_Months(trans_month,-2)
 ) AS dt
GROUP BY trans_month
ORDER BY trans_month