在案例中使用聚合方法的视图中创建列...当表达式

Creating Columns in a View That Use an Aggregate Method in a Case...When Expression

我正在尝试在 SQL 服务器中创建一个视图,该视图呈现来自 3 table 的列并创建 4 个新列。这些新列使用 SQL“Case...When”语法根据同一 table 中相邻列 [Portfolio Report Category] ​​的值有条件地呈现现有字段的 SUM。

objective 是显示单个账户 4 种不同资产类别的总市值。现在,对于单个 [投资组合报告类别],一个 [帐号] 可以有许多记录和许多 [投资金额]。所以很明显,这个视图应该允许 [Account Number] 只有一个记录,其中包含 4 个满足“Case...When”条件的总货币值。

我读过类似的线程,但是 none 它在条件块中的“Then”关键字之后解决了聚合方法。当我将 Sum() 放在“Case”之前并在“Then”之后将其删除时,没有错误,但计算是错误的:在许多情况下,它们要高得多。我的印象是简单的 Try_Convert 到 money 就足够了,实际上如果我执行 SUM(Try_Convert(money, [Market_Value]) Where [Account Number] = 'x',结果是正确的。但是当我创建视图时不是。

下面是使用SELECT测试以下代码时的错误:

Column 'KTHoldings.Portfolio Report Category' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

下面是 KTHoldings table 返回单个帐户的所有记录。我基本上需要我视图的 [Other Total Value] 列来汇总其 [Market Value] 数据。

CREATE VIEW VW_KTAccountsADR AS (
    SELECT adr.[Account Number], adr.[Account_ Display Name], adr.[Account Category Code], adr.[Division Code], adr.[Division Name], adr.[Market Value Amount],
    CASE WHEN kth.[Portfolio Report Category] = '705' THEN SUM((TRY_CONVERT(money, kth.[Market Value]))) ELSE '0.00' END AS [Crypto Total Value], 
    CASE WHEN kth.[Portfolio Report Category] = '691' THEN SUM((TRY_CONVERT(money, kth.[Market Value]))) ELSE '0.00' END AS [Precious Metal Total Value],
    CASE WHEN kth.[Portfolio Report Category] IN ('010', '011', '020', '025', '030') THEN SUM((TRY_CONVERT(money, kth.[Market Value]))) ELSE '0.00' END AS [Stock Total Value],
    CASE WHEN kth.[Portfolio Report Category] NOT IN ('010', '011', '020', '025', '030', '691', '705') THEN SUM((TRY_CONVERT(money, kth.[Market Value]))) ELSE '0.00' END AS [Other Total Value],
    ktc.[Available Cash Amount] AS [CASH TOTAL]
    FROM KTAccountsADR adr
    INNER JOIN KTHoldings kth
    ON adr.[Account Number] = kth.[Account Number]
    INNER JOIN KTCash ktc 
    ON adr.[Account Number] = ktc.[Account Number]
    GROUP BY adr.[Account Number], adr.[Account_ Display Name], adr.[Account Category Code], adr.[Division Code], adr.[Division Code], adr.[Division Name], adr.[Market Value Amount], ktc.[Available Cash Amount]
)

KTAccountsADR Table

Account Number          Display Name      Division Code   Market Value Amount
07007835        Frank C Thomas Roth IRA           27             390410.98
07007835        Frank C Thomas Roth IRA           27             390410.98
07007835        Frank C Thomas Roth IRA           27             390410.98
07007835        Frank C Thomas Roth IRA           27             390410.98
001000          Carl S Sykes Roth IRA             27           196338.1292            
001000          Carl S Sykes Roth IRA             27           196338.1292
001000          Carl S Sykes Roth IRA             27           196338.1292

KTHoldings Table

Account Number  Display Name    Market Value    Portfolio Report Category
001000  Carl S Sykes Roth IRA   9998.4792        600
001000  Carl S Sykes Roth IRA   43467.09         600
001000  Carl S Sykes Roth IRA   84524.71         600

KTCash Table

Account Number  Available Cash Amount
001000               58347.85

您需要将 case 放入 sum:

SUM(CASE WHEN kth.[Portfolio Report Category] = '705' THEN TRY_CONVERT(money, kth.[Market Value]) ELSE '0.00' END) AS [Crypto Total Value], 

这是一个工作示例:

declare @Adr table ([Account Number] varchar(6), [Account_ Display Name] varchar(64), [Account Category Code] varchar, [Division Code] varchar, [Division Name] varchar, [Market Value Amount] money);
declare @Kth table ([Account Number] varchar(6), [Portfolio Report Category] varchar(3), [Market Value] money);
declare @Ktc table ([Account Number] varchar(6), [Available Cash Amount] money);

insert into @Adr ([Account Number], [Account_ Display Name])
values ('001000', 'Carl S Sykes Roth IRA');

insert into @Kth ([Account Number], [Market Value], [Portfolio Report Category])
values ('001000', 9998.4792, '600'),
('001000', 43467.09, '600'),
('001000', 84524.71, '600');

insert into @Ktc ([Account Number])
values ('001000');

SELECT adr.[Account Number], adr.[Account_ Display Name], adr.[Account Category Code], adr.[Division Code], adr.[Division Name], adr.[Market Value Amount]
  , SUM(CASE WHEN kth.[Portfolio Report Category] = '705' THEN (TRY_CONVERT(money, kth.[Market Value])) ELSE 0 END) AS [Crypto Total Value] 
  , SUM(CASE WHEN kth.[Portfolio Report Category] = '691' THEN (TRY_CONVERT(money, kth.[Market Value])) ELSE 0 END) AS [Precious Metal Total Value]
  , SUM(CASE WHEN kth.[Portfolio Report Category] IN ('010', '011', '020', '025', '030') THEN (TRY_CONVERT(money, kth.[Market Value])) ELSE 0 END) AS [Stock Total Value]
  , SUM(CASE WHEN kth.[Portfolio Report Category] NOT IN ('010', '011', '020', '025', '030', '691', '705') THEN (TRY_CONVERT(money, kth.[Market Value])) ELSE 0 END) AS [Other Total Value]
  , ktc.[Available Cash Amount] AS [CASH TOTAL]
FROM @Adr adr
INNER JOIN @Kth kth ON adr.[Account Number] = kth.[Account Number]
INNER JOIN @Ktc ktc  ON adr.[Account Number] = ktc.[Account Number]
GROUP BY adr.[Account Number], adr.[Account_ Display Name], adr.[Account Category Code], adr.[Division Code], adr.[Division Code], adr.[Division Name], adr.[Market Value Amount], ktc.[Available Cash Amount];

returns(删除了 un-necessary 列):

Account Number  Crypto Total Value  Precious Metal Total Value  Stock Total Value   Other Total Value   CASH TOTAL
001000          0.00                0.00                        0.00                137990.2792         NULL

编辑:由于您现在已经添加了示例数据,所以您得到不正确值的原因是因为您在 KTAccountsADR 中有重复的行,然后在 KTHoldings [=32] 中有多个行=].解决重复项,在 sum.

中使用 case 时,您将获得正确的值

请注意,确保从 case 表达式的所有分支返回相同数据类型的最佳做法。