SQL 查询中的累积计算与分层计算或带条件逻辑的内联 Table 值函数?
Cumulative vs. Tiered Calculation in SQL Query or Inline Table Value Function with Conditional Logic?
我正在处理两个 table 数据,但使用不同的方法来导出下面两个不同的所需输出。
第一个是累积层计算,第二个只是基于范围的分层查找。我需要能够return 计算行项目事务,该计算基于某些使用外键到其他维度 table 的 JOINS,即帐户和区域以及层类型。例如,单个帐户可以根据区域 and/or 帐户的 ID 进行累积或分层计算。
Link 到 DB Fiddle
Type ID
Name
1
Cumulative
2
Tiered
分层table:
Account ID
Type ID
Region ID
TierNo
Min
Max
Total A
Total B
101
1
2
1
0
10000
.90
.10
101
1
2
2
10001
30000
.60
.40
101
1
2
3
30001
100000
.40
.60
101
1
2
4
100001
500000
.40
.60
101
1
2
5
500001
999999999999
.20
.80
102
1
3
1
0
7800
.80
.20
102
1
3
2
7801
12800
.70
.30
102
1
3
3
12801
34000
.60
.40
102
1
3
4
34001
50000
.50
.50
102
1
3
5
5000 1
999999999999
.50
.50
103
2
1
1
0
10000
.90
.10
103
2
1
2
10001
30000
.60
.40
103
2
1
3
30001
100000
.40
.60
103
2
1
4
100001
500000
.40
.60
103
2
1
5
500001
999999999999
.20
.80
当前table样本:
Trans ID
Account ID
Type ID
Region ID
GrossAmt
Total A %
Total A $
Net Amt
100001
101
1
2
42650
100002
102
1
3
42650
100003
103
2
1
42650
期望的输出:
Trans ID
Account ID
Type ID
Region ID
GrossAmt
Total A %
Total A $
Net Amt
100001
101
1
2
42650
0.611
26059.99
16589.99
100002
102
1
3
42650
0.628
26784.98
15864.99
100003
103
2
1
42650
0.40
17060.00
25590.00
我已经能够对之前的 post 进行一些编辑以获取帐户,但似乎无法弄清楚 TransID 100003 中分层查找值的逻辑。
理想情况下,我更愿意在 table 值函数(或两个)中创建此逻辑,然后将其合并到一个视图中,我将使用该视图使用 C# 在 Web 表单中进行报告。
SELECT
c.*,
[Total A %] = t.Total / c.GrossAmt,
[Total A $] = t.Total,
[Net Amt] = c.GrossAmt - t.Total
FROM #temp c
INNER JOIN Accounts a ON a.[Account ID] = c.[Account ID]
CROSS APPLY (
SELECT
Total = SUM((v.ActualMax - t.[Min]) * t.[Total A %])
FROM [dbo].[Tiered Table] t
CROSS APPLY (VALUES(
CASE WHEN c.GrossAmt < t.[Max] THEN c.GrossAmt ELSE t.[Max] END
)) v(ActualMax)
WHERE c.GrossAmt > t.[Min] AND t.[Account ID] = c.[Account ID]
) t;
任何想法或指导都将非常有帮助和感激。
这似乎是 AND
OR
逻辑的简单问题。 您需要排除 TypeID = 2
并且还具有他们的最大值 低于 GrossAmt
的水平。
然后您只需有条件地汇总总金额(仅对于分层行,只有一行)或仅汇总该层的金额(对于累积层)。
SELECT
c.*,
[Total A %] = t.Total / c.GrossAmt,
[Total A $] = t.Total,
[Net Amt] = c.GrossAmt - t.Total
FROM CurrentData c
INNER JOIN Accounts a ON a.[AccountID] = c.[AccountID]
CROSS APPLY (
SELECT
Total = SUM(CASE WHEN t.TypeID = 2 THEN v.GrossAmt ELSE (v.ActualMax - t.[Min]) END * t.[Total A])
FROM [dbo].[Tiers] t
CROSS APPLY (VALUES(
CASE WHEN c.GrossAmt < t.[Max] THEN c.GrossAmt ELSE t.[Max] END,
c.GrossAmt
)) v(ActualMax, GrossAmt)
WHERE t.[AccountID] = c.[AccountID]
AND t.TypeID = c.TypeID
AND t.RegionID = c.RegionID
AND c.GrossAmt > t.[Min]
AND (t.TypeID = 1 OR c.GrossAmt <= t.Max)
) t;
The second CROSS APPLY
is only necessary because of aggregating outer values. You don't need this if you place it in a function, as shown in your previous question.
注意这里应该使用半开区间。换句话说,Min
或 Max
应该是互斥的。否则可能会出现“漏网之鱼”的价值观。
我正在处理两个 table 数据,但使用不同的方法来导出下面两个不同的所需输出。
第一个是累积层计算,第二个只是基于范围的分层查找。我需要能够return 计算行项目事务,该计算基于某些使用外键到其他维度 table 的 JOINS,即帐户和区域以及层类型。例如,单个帐户可以根据区域 and/or 帐户的 ID 进行累积或分层计算。
Link 到 DB Fiddle
Type ID | Name |
---|---|
1 | Cumulative |
2 | Tiered |
分层table:
Account ID | Type ID | Region ID | TierNo | Min | Max | Total A | Total B |
---|---|---|---|---|---|---|---|
101 | 1 | 2 | 1 | 0 | 10000 | .90 | .10 |
101 | 1 | 2 | 2 | 10001 | 30000 | .60 | .40 |
101 | 1 | 2 | 3 | 30001 | 100000 | .40 | .60 |
101 | 1 | 2 | 4 | 100001 | 500000 | .40 | .60 |
101 | 1 | 2 | 5 | 500001 | 999999999999 | .20 | .80 |
102 | 1 | 3 | 1 | 0 | 7800 | .80 | .20 |
102 | 1 | 3 | 2 | 7801 | 12800 | .70 | .30 |
102 | 1 | 3 | 3 | 12801 | 34000 | .60 | .40 |
102 | 1 | 3 | 4 | 34001 | 50000 | .50 | .50 |
102 | 1 | 3 | 5 | 5000 1 | 999999999999 | .50 | .50 |
103 | 2 | 1 | 1 | 0 | 10000 | .90 | .10 |
103 | 2 | 1 | 2 | 10001 | 30000 | .60 | .40 |
103 | 2 | 1 | 3 | 30001 | 100000 | .40 | .60 |
103 | 2 | 1 | 4 | 100001 | 500000 | .40 | .60 |
103 | 2 | 1 | 5 | 500001 | 999999999999 | .20 | .80 |
当前table样本:
Trans ID | Account ID | Type ID | Region ID | GrossAmt | Total A % | Total A $ | Net Amt |
---|---|---|---|---|---|---|---|
100001 | 101 | 1 | 2 | 42650 | |||
100002 | 102 | 1 | 3 | 42650 | |||
100003 | 103 | 2 | 1 | 42650 |
期望的输出:
Trans ID | Account ID | Type ID | Region ID | GrossAmt | Total A % | Total A $ | Net Amt |
---|---|---|---|---|---|---|---|
100001 | 101 | 1 | 2 | 42650 | 0.611 | 26059.99 | 16589.99 |
100002 | 102 | 1 | 3 | 42650 | 0.628 | 26784.98 | 15864.99 |
100003 | 103 | 2 | 1 | 42650 | 0.40 | 17060.00 | 25590.00 |
我已经能够对之前的 post 进行一些编辑以获取帐户,但似乎无法弄清楚 TransID 100003 中分层查找值的逻辑。
理想情况下,我更愿意在 table 值函数(或两个)中创建此逻辑,然后将其合并到一个视图中,我将使用该视图使用 C# 在 Web 表单中进行报告。
SELECT
c.*,
[Total A %] = t.Total / c.GrossAmt,
[Total A $] = t.Total,
[Net Amt] = c.GrossAmt - t.Total
FROM #temp c
INNER JOIN Accounts a ON a.[Account ID] = c.[Account ID]
CROSS APPLY (
SELECT
Total = SUM((v.ActualMax - t.[Min]) * t.[Total A %])
FROM [dbo].[Tiered Table] t
CROSS APPLY (VALUES(
CASE WHEN c.GrossAmt < t.[Max] THEN c.GrossAmt ELSE t.[Max] END
)) v(ActualMax)
WHERE c.GrossAmt > t.[Min] AND t.[Account ID] = c.[Account ID]
) t;
任何想法或指导都将非常有帮助和感激。
这似乎是 AND
OR
逻辑的简单问题。 您需要排除 TypeID = 2
并且还具有他们的最大值 低于 GrossAmt
的水平。
然后您只需有条件地汇总总金额(仅对于分层行,只有一行)或仅汇总该层的金额(对于累积层)。
SELECT
c.*,
[Total A %] = t.Total / c.GrossAmt,
[Total A $] = t.Total,
[Net Amt] = c.GrossAmt - t.Total
FROM CurrentData c
INNER JOIN Accounts a ON a.[AccountID] = c.[AccountID]
CROSS APPLY (
SELECT
Total = SUM(CASE WHEN t.TypeID = 2 THEN v.GrossAmt ELSE (v.ActualMax - t.[Min]) END * t.[Total A])
FROM [dbo].[Tiers] t
CROSS APPLY (VALUES(
CASE WHEN c.GrossAmt < t.[Max] THEN c.GrossAmt ELSE t.[Max] END,
c.GrossAmt
)) v(ActualMax, GrossAmt)
WHERE t.[AccountID] = c.[AccountID]
AND t.TypeID = c.TypeID
AND t.RegionID = c.RegionID
AND c.GrossAmt > t.[Min]
AND (t.TypeID = 1 OR c.GrossAmt <= t.Max)
) t;
The second
CROSS APPLY
is only necessary because of aggregating outer values. You don't need this if you place it in a function, as shown in your previous question.
注意这里应该使用半开区间。换句话说,Min
或 Max
应该是互斥的。否则可能会出现“漏网之鱼”的价值观。