问题描述
我正在尝试在SQL Server中创建一个视图,该视图呈现3个表中的列并创建4个NEW列。这些新列使用SQL“ Case ... When”语法根据同一表中相邻列[Portfolio Report Category]的值有条件地呈现现有字段的SUM。
目标是显示4个不同资产类别的单个帐户的总市值。现在,一个[帐号]可以有一个[投资组合报告类别]多个记录,其中[投资金额]。因此,很明显,此视图应允许[帐号]仅有一个记录,且该记录具有4个满足“ Case ... When”条件的总货币值。
我已经读过类似的线程,但是没有一个在条件块中的“ Then”关键字之后解决聚合方法。当我将Sum()放在“ Case”之前,并在“ Then”之后删除它时,没有错误,但计算错误:在许多情况下,它们要高得多。我的印象是,简单的Try_Convert到钱就足够了,确实,如果我执行SUM(Try_Convert(money,[Market_Value])其中[Account Number] ='x',结果是正确的。 m创建视图。
以下是使用SELECT测试以下代码时的错误:
选择列表中的“ KTHoldings.Portfolio报告类别”列无效,因为它既不包含在聚合函数中,也不包含在GROUP BY子句中。
下面是KTHoldings表,该表返回单个帐户的所有记录。我基本上需要视图的[其他总价值]列来汇总其[市场价值]数据。
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','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],ktc.[Available Cash Amount]
)
KTAccountsADR表
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表
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表
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,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','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],ktc.[Available Cash Amount];
哪个返回(删除了不必要的列):
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
表中有多行。解决重复项,在case
中使用sum
时,您将获得正确的值。
请注意,其最佳做法是确保您从case
表达式的所有分支返回相同的数据类型。