Filtering based on SSRS total/sum

ぃ、小莉子 提交于 2019-12-12 02:37:32

问题


I am using Visual Studio 2010 and SQL Server 2012.

I have searched the net and the stackoverflow archives and found a few others who have had this problem but I could not get their solutions to work for me. The problem involves filtering based on the aggregate value of a dataset using a user definable report parameter.

I have the following report.

The ultimate goal of this report is to filter portfolios that have a user definable % of cash as a percent of total assets. The default will be 30% or greater. So for example if a Portfolios total market value was $100,000 and their cash asset class was $40,000 this would be a cash perent of 40% and this portfolio would appear on the report.

I have been able to select just the cash asset class using a filter on the dataset itself so that is not an issue. I easily added a cash percent parameter to the dataset but soon realized this is filtering on the row detail not the aggregated sum, and sometimes portfolios have multiple cash accounts. I need the sum of all cash accounts so I can truly know if cash is 30% or greater of total market value.

At first I thought the report was working correctly.

But after cross referencing this against another report I realized this portfolio only has 2.66 % total Cash because it has a large negative balance in a second cash account as well. It's the sum of all cash accounts I care about.

I want to filter portfolios that have >= cash based on the total line not the detail lines. I suspect I may need to alter the dataset using the scalar function SUM() then building a parameter off that, but I have not had success writing a query to do that. I also would be very interested to know if somehow this can be done in the .rdl layer rather than at the sql dataset level. The SQL for this is a little complicated because the program that this is reporting on requries the use of SQL functions, stored procedures, and parameters.

If the solution involves altering the query to include sum() in the dataset itself, I suspect it is line 20 that needs to be summed

a.PercentAssets,

Here is the data set for the report.

https://www.dropbox.com/s/bafdo2i6pfvdkk4/CashPercentDataSet.sql

and here is the .rdl file.

https://www.dropbox.com/s/htg09ypyh7f1a98/cashpercent2.rdl

Thank you


回答1:


I would do this in SQL personally. You can use a SUM() aggregate to get the value you're after for each account. You won't want to sum the percents though, you'll want to SUM the values and then create the percent afterwards once you have the totals. A sum of averages isn't the same as an average of sums (except in some circumstances but we can't assume that).

I would do something like this, though you'll probably need to tweak it to get it working correctly for you. (I also may not fully understanding the meaning of all the columns you're using).

SELECT PortfolioBaseCode,totalValue,cashValue,
    (CAST(cashValue AS FLOAT)/totalValue) * 100 AS pcntCash
FROM (
    SELECT b.PortfolioBaseCode,
        SUM(a.MarketValue) AS totalValue
        SUM(CASE s.SecuritySymbol WHEN 'CASH' THEN a.MarketValue ELSE 0 END) AS cashValue
    FROM APXUser.fAppraisal (@ReportData) a 
    LEFT JOIN APXUser.vPortfolioBaseSettingEx b ON b.PortfolioBaseID = a.PortfolioBaseID 
    LEFT JOIN APXUser.vSecurityVariant s ON s.SecurityID = a.SecurityID 
        AND s.SecTypeCode = a.SecTypeCode 
        AND s.IsShort = a.IsShortPosition 
        AND a.PercentAssets >= @PercentAssets
    GROUP BY b.PortfolioBaseCode
) AS t
WHERE (CAST(cashValue AS FLOAT)/totalValue)>=@pcntParameter

Alternatively you can use the HAVING clause to filter aggregate functions like a WHERE clause would (though I find this a little less readable):

SELECT b.PortfolioBaseCode,
    SUM(a.MarketValue) AS totalValue
    SUM(CASE s.SecuritySymbol WHEN 'CASH'  THEN a.MarketValue ELSE 0 END) AS cashValue,
    (SUM(a.MarketValue)/SUM(CASE s.SecuritySymbol WHEN 'CASH'  THEN a.MarketValue ELSE 0 END))*100 AS cashPcnt
FROM APXUser.fAppraisal (@ReportData) a 
LEFT JOIN APXUser.vPortfolioBaseSettingEx b ON b.PortfolioBaseID = a.PortfolioBaseID 
LEFT JOIN APXUser.vSecurityVariant s ON s.SecurityID = a.SecurityID 
    AND s.SecTypeCode = a.SecTypeCode 
    AND s.IsShort = a.IsShortPosition 
    AND a.PercentAssets >= @PercentAssets
GROUP BY b.PortfolioBaseCode
HAVING (SUM(a.MarketValue)/SUM(CASE s.SecuritySymbol WHEN 'CASH'  THEN a.MarketValue ELSE 0 END))>=@pcntParameter

Basically you can use grouping and aggregate functions to get the total value and the cash value for each account and then calculate the proper percentage from that. This will take into account any negatives, etc in other holdings.

Some references for aggregate function and grouping:

MSDN - GROUP BY (TSQL)

MSDN - Aggregate Functions

MSDN - HAVING Clause

If you find you're needing to do some kind of aggregation but you cannot group your results you should look into using the TSQL window functions which are very handy:

Working with Window Functions in SQL Server

MSDN - OVER Clause



来源:https://stackoverflow.com/questions/19173000/filtering-based-on-ssrs-total-sum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!