如何在不同条件下聚合两个不同列中的值?
How to aggregate values in two different columns under different criteria?
这是我想要处理的 table 数据:
CUST_REF
ACC_NO
JOINT_ACC
PRODUCT
NUM_OF_ACC
CALC_FEE
ACTUAL_FEE
DIFF
100
ABC123
N
ACCOUNT
4
140.68
104.14
36.54
100
ABC456
N
STOCKS
4
41.72
30.24
11.48
100
XYZ123
N
ISA
4
48.26
32.27
15.99
100
XYZ444
Y
PENSION
4
3.15
0.00
3.15
我现在需要在费用上限的影响下工作,费用上限因帐户是否共同持有而异。 JOINT_ACC字段中的Y表示联名账户。
所有个人账户的费用上限为每个客户每月 166.67 (JOINT_ACC = 'N') - 即所有个人账户的总费用不能超过 166.67。但是,对于联名账户,上限适用于个人账户级别。换句话说,当 JOINT_ACC = 'Y' 时 CALC_FEE 不能超过 166.67 - 在这种情况下,帐户的费用远低于 166.67,所以它保持原样(我不关心实际费用为 0,这对于伟大和善良的人来说是一个单独的问题。
在这个例子中,实际费用不知何故已经考虑了这个信息——如果你把 ACTUAL_FEE 列中的三个条目加起来,它们加起来是 166.67。
因此我想:
- 根据 JOINT_ACC 标志聚合 CALC_FEE 条目,并应用基于 CASE 的条件在费用上限内工作
- 汇总个人和联名账户的 ACTUAL_FEE(我不想在此处应用费用上限,因为我的 objective 是将计算的费用与实际收取的费用进行比较)。
所以实际上我的理想输出 table 看起来像这样:
CUST_REF
ACC_NO
JOINT_ACC
PRODUCT
NUM_OF_ACC
CALC_FEE
ACTUAL_FEE
DIFF
100
ABC123
N
ACCOUNT
4
166.67
166.67
0.00
100
ABC456
N
STOCKS
4
166.67
166.67
0.00
100
XYZ123
N
ISA
4
166.67
166.67
0.00
100
XYZ444
Y
PENSION
4
3.15
0.00
0.00
这是我到目前为止尝试过的方法:
SELECT
A.CUST_REF,
A.ACC_NO,
A.JOINT_ACC,
A.PRODUCT,
A.NUM_OF_ACC,
SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.ACC_NO, A.JOINT_ACC) AS FEES_CHARGED,
CASE
WHEN A.JOINT_ACC_IND = 'N'
THEN
(CASE
WHEN (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO)) > 166.67 THEN (166.67)
ELSE (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO))
END)
WHEN A.JOINT_ACC_IND = 'Y'
THEN
(CASE
WHEN (C.CALC_FEE) > 166.67 THEN (166.67)
ELSE (C.CALC_FEE)
END)
END
AS ADJ_FEE_CALC,
((CASE
WHEN A.JOINT_ACC_IND = 'N'
THEN
(CASE
WHEN (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO)) > 166.67 THEN (166.67)
ELSE (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO))
END)
WHEN A.JOINT_ACC_IND = 'Y'
THEN
(CASE
WHEN (C.CALC_FEE) > 166.67 THEN (166.67)
ELSE (C.CALC_FEE)
END)
END) - (SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.ACC_NO, A.JOINT_ACC))) AS DIFF
FROM V_FEES_TABLE A
LEFT JOIN V_FEES_TABLE B ON A.CUST_REF = B.CUST_REF AND A.ACC_NO = B.ACC_NO AND B.JOINT_ACC = 'N'
LEFT JOIN V_FEES_TABLE C ON A.CUST_REF = C.CUST_REF AND A.ACC_NO = C.ACC_NO AND C.JOINT_ACC = 'Y'
这个查询花费了很长时间 运行(我几分钟前检查时超过一个小时)。显然,我做的事情根本上是错误的/效率低下的。我不知道它是否有所作为,但 V_FEES_TABLE
是一个构建在另一个视图之上的视图,该视图又引用数据库中的核心 tables。
请帮忙!提前致谢。
编辑:
在某些情况下,下面建议的代码会引发误报:
CUST_REF
ACC_NO
JOINT_ACC
PRODUCT
NUM_OF_ACC
CALC_FEE
ACTUAL_FEE
CUST_FEE_CALC
ACTUAL_CUST_FEE_CHARGED
DIFF
100
ABC123
N
ACCOUNT
1
95.45
94.29
166.67
379.3
-212.63
100
ABC123
N
ACCOUNT
1
95.45
95.36
166.67
379.3
-212.63
我用来重新运行工作的代码是:
SELECT
A.CUST_REF,
A.ACC_NO,
A.JOINT_ACC,
A.PRODUCT,
A.NUM_OF_ACC,
A.CALC_FEE,
A.ACTUAL_FEE,
(CASE WHEN JOINT_ACC = 'Y' AND CALC_FEE < 166.67
THEN CALC_FEE
WHEN JOINT_ACC = 'Y'
THEN 166.67
WHEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC) < 166.67
THEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC)
ELSE 166.67
END) as CUST_FEE_CALC,
SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.JOINT_ACC) AS ACTUAL_CUST_FEE_CHARGED,
(CASE WHEN JOINT_ACC = 'Y' AND CALC_FEE < 166.67
THEN CALC_FEE
WHEN JOINT_ACC = 'Y'
THEN 166.67
WHEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC) < 166.67
THEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC)
ELSE 166.67
END) - SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.JOINT_ACC)
as DIFF
FROM FEES_TABLE A
在某些情况下,同一帐户在同一时期内以不同的金额计费两次 - 实际上,SQL 出于汇总目的将其视为两个单独的帐户。这无意中扭曲了我自己的计算,因为它两次加起来是 95.45,并显示客户级费用为 166.67,考虑到上面根据 Gordon 的解决方案计算的上限。
我希望 SQL 将计算的客户费用保留在帐户级别,但将实际收取的费用相加,因为我不确定为什么我在这里看到 94.29 和 95.36 的不同数字。因此,我希望看到:
CUST_REF
ACC_NO
JOINT_ACC
PRODUCT
NUM_OF_ACC
CALC_FEE
ACTUAL_FEE
CUST_FEE_CALC
ACTUAL_CUST_FEE_CHARGED
DIFF
100
ABC123
N
ACCOUNT
1
95.45
94.29
95.45
189.65
-94.20
100
ABC123
N
ACCOUNT
1
95.45
95.36
95.45
189.65
-94.20
我试图修改 PARTITION BY
条件以也包括 ACC_NO
列,但没有成功。有什么想法吗?
我不明白为什么需要任何连接,只是 window 函数。获取计算的费用:
SELECT FT.*,
(CASE WHEN JOINT_ACC = 'Y' AND CALC_FEE < 166.67
THEN CALC_FEE
WHEN JOINT_ACC = 'Y'
THEN 166.67
WHEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC) < 166.67
THEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC)
ELSE 166.67
END) as IMPUTED_CALC_FEE
FROM V_FEES_TABLE FT
这是我想要处理的 table 数据:
CUST_REF | ACC_NO | JOINT_ACC | PRODUCT | NUM_OF_ACC | CALC_FEE | ACTUAL_FEE | DIFF |
---|---|---|---|---|---|---|---|
100 | ABC123 | N | ACCOUNT | 4 | 140.68 | 104.14 | 36.54 |
100 | ABC456 | N | STOCKS | 4 | 41.72 | 30.24 | 11.48 |
100 | XYZ123 | N | ISA | 4 | 48.26 | 32.27 | 15.99 |
100 | XYZ444 | Y | PENSION | 4 | 3.15 | 0.00 | 3.15 |
我现在需要在费用上限的影响下工作,费用上限因帐户是否共同持有而异。 JOINT_ACC字段中的Y表示联名账户。
所有个人账户的费用上限为每个客户每月 166.67 (JOINT_ACC = 'N') - 即所有个人账户的总费用不能超过 166.67。但是,对于联名账户,上限适用于个人账户级别。换句话说,当 JOINT_ACC = 'Y' 时 CALC_FEE 不能超过 166.67 - 在这种情况下,帐户的费用远低于 166.67,所以它保持原样(我不关心实际费用为 0,这对于伟大和善良的人来说是一个单独的问题。
在这个例子中,实际费用不知何故已经考虑了这个信息——如果你把 ACTUAL_FEE 列中的三个条目加起来,它们加起来是 166.67。
因此我想:
- 根据 JOINT_ACC 标志聚合 CALC_FEE 条目,并应用基于 CASE 的条件在费用上限内工作
- 汇总个人和联名账户的 ACTUAL_FEE(我不想在此处应用费用上限,因为我的 objective 是将计算的费用与实际收取的费用进行比较)。
所以实际上我的理想输出 table 看起来像这样:
CUST_REF | ACC_NO | JOINT_ACC | PRODUCT | NUM_OF_ACC | CALC_FEE | ACTUAL_FEE | DIFF |
---|---|---|---|---|---|---|---|
100 | ABC123 | N | ACCOUNT | 4 | 166.67 | 166.67 | 0.00 |
100 | ABC456 | N | STOCKS | 4 | 166.67 | 166.67 | 0.00 |
100 | XYZ123 | N | ISA | 4 | 166.67 | 166.67 | 0.00 |
100 | XYZ444 | Y | PENSION | 4 | 3.15 | 0.00 | 0.00 |
这是我到目前为止尝试过的方法:
SELECT
A.CUST_REF,
A.ACC_NO,
A.JOINT_ACC,
A.PRODUCT,
A.NUM_OF_ACC,
SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.ACC_NO, A.JOINT_ACC) AS FEES_CHARGED,
CASE
WHEN A.JOINT_ACC_IND = 'N'
THEN
(CASE
WHEN (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO)) > 166.67 THEN (166.67)
ELSE (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO))
END)
WHEN A.JOINT_ACC_IND = 'Y'
THEN
(CASE
WHEN (C.CALC_FEE) > 166.67 THEN (166.67)
ELSE (C.CALC_FEE)
END)
END
AS ADJ_FEE_CALC,
((CASE
WHEN A.JOINT_ACC_IND = 'N'
THEN
(CASE
WHEN (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO)) > 166.67 THEN (166.67)
ELSE (SUM(B.CALC_FEE) OVER PARTITION BY (A.CUST_REF, A.ACC_NO))
END)
WHEN A.JOINT_ACC_IND = 'Y'
THEN
(CASE
WHEN (C.CALC_FEE) > 166.67 THEN (166.67)
ELSE (C.CALC_FEE)
END)
END) - (SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.ACC_NO, A.JOINT_ACC))) AS DIFF
FROM V_FEES_TABLE A
LEFT JOIN V_FEES_TABLE B ON A.CUST_REF = B.CUST_REF AND A.ACC_NO = B.ACC_NO AND B.JOINT_ACC = 'N'
LEFT JOIN V_FEES_TABLE C ON A.CUST_REF = C.CUST_REF AND A.ACC_NO = C.ACC_NO AND C.JOINT_ACC = 'Y'
这个查询花费了很长时间 运行(我几分钟前检查时超过一个小时)。显然,我做的事情根本上是错误的/效率低下的。我不知道它是否有所作为,但 V_FEES_TABLE
是一个构建在另一个视图之上的视图,该视图又引用数据库中的核心 tables。
请帮忙!提前致谢。
编辑:
在某些情况下,下面建议的代码会引发误报:
CUST_REF | ACC_NO | JOINT_ACC | PRODUCT | NUM_OF_ACC | CALC_FEE | ACTUAL_FEE | CUST_FEE_CALC | ACTUAL_CUST_FEE_CHARGED | DIFF |
---|---|---|---|---|---|---|---|---|---|
100 | ABC123 | N | ACCOUNT | 1 | 95.45 | 94.29 | 166.67 | 379.3 | -212.63 |
100 | ABC123 | N | ACCOUNT | 1 | 95.45 | 95.36 | 166.67 | 379.3 | -212.63 |
我用来重新运行工作的代码是:
SELECT
A.CUST_REF,
A.ACC_NO,
A.JOINT_ACC,
A.PRODUCT,
A.NUM_OF_ACC,
A.CALC_FEE,
A.ACTUAL_FEE,
(CASE WHEN JOINT_ACC = 'Y' AND CALC_FEE < 166.67
THEN CALC_FEE
WHEN JOINT_ACC = 'Y'
THEN 166.67
WHEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC) < 166.67
THEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC)
ELSE 166.67
END) as CUST_FEE_CALC,
SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.JOINT_ACC) AS ACTUAL_CUST_FEE_CHARGED,
(CASE WHEN JOINT_ACC = 'Y' AND CALC_FEE < 166.67
THEN CALC_FEE
WHEN JOINT_ACC = 'Y'
THEN 166.67
WHEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC) < 166.67
THEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC)
ELSE 166.67
END) - SUM(A.ACTUAL_FEE) OVER (PARTITION BY A.CUST_REF, A.JOINT_ACC)
as DIFF
FROM FEES_TABLE A
在某些情况下,同一帐户在同一时期内以不同的金额计费两次 - 实际上,SQL 出于汇总目的将其视为两个单独的帐户。这无意中扭曲了我自己的计算,因为它两次加起来是 95.45,并显示客户级费用为 166.67,考虑到上面根据 Gordon 的解决方案计算的上限。
我希望 SQL 将计算的客户费用保留在帐户级别,但将实际收取的费用相加,因为我不确定为什么我在这里看到 94.29 和 95.36 的不同数字。因此,我希望看到:
CUST_REF | ACC_NO | JOINT_ACC | PRODUCT | NUM_OF_ACC | CALC_FEE | ACTUAL_FEE | CUST_FEE_CALC | ACTUAL_CUST_FEE_CHARGED | DIFF |
---|---|---|---|---|---|---|---|---|---|
100 | ABC123 | N | ACCOUNT | 1 | 95.45 | 94.29 | 95.45 | 189.65 | -94.20 |
100 | ABC123 | N | ACCOUNT | 1 | 95.45 | 95.36 | 95.45 | 189.65 | -94.20 |
我试图修改 PARTITION BY
条件以也包括 ACC_NO
列,但没有成功。有什么想法吗?
我不明白为什么需要任何连接,只是 window 函数。获取计算的费用:
SELECT FT.*,
(CASE WHEN JOINT_ACC = 'Y' AND CALC_FEE < 166.67
THEN CALC_FEE
WHEN JOINT_ACC = 'Y'
THEN 166.67
WHEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC) < 166.67
THEN SUM(CALC_FEE) OVER (PARTITION BY CUST_REF, JOINT_ACC)
ELSE 166.67
END) as IMPUTED_CALC_FEE
FROM V_FEES_TABLE FT