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
我有一个 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