在 SSRS 中计算百分位数
Calculate Percentile in SSRS
我们需要根据共享数据集计算 SSRS 报告中的百分位数(第 95 位和第 99 位),该共享数据集 return 按 15 分钟间隔聚合数据。百分位数需要针对整个一天,但根据合约。
为了论证,假设这是我们的数据:
select
'Test' as [ContractName],
1 as [Value]
union all
select
'Test' as [ContractName],
3 as [Value]
union all
select
'Test' as [ContractName],
4 as [Value]
union all
select
'Test' as [ContractName],
6 as [Value]
union all
select
'Test' as [ContractName],
7 as [Value]
union all
select
'Test' as [ContractName],
36 as [Value]
union all
select
'Test' as [ContractName],
56 as [Value]
union all
select
'Test' as [ContractName],
798 as [Value]
union all
select
'Test' as [ContractName],
324 as [Value]
union all
select
'Test' as [ContractName],
456 as [Value]
union all
select
'Test' as [ContractName],
657 as [Value]
union all
select
'Test' as [ContractName],
658 as [Value]
这几乎已排序(我创建它时),但数据本身不会在实际应用程序中。
我需要能够在不更改 SQL 的情况下从此数据集中获取百分位数,因为它是用于合同报告的共享数据集,无法更改。共享数据集用于确保整套报告的一致性。因此,解决方案必须在最终报告输出的 tablix 中。
我查看了 SSRS expression - query from dataset, with group and noticed that it has the same basic usage as this Find the median of a calculated field in SSRS 2012, which comes from https://blogs.msdn.microsoft.com/robertbruckner/2008/07/21/using-group-variables-in-reporting-services-2008-for-custom-aggregation/ 并且需要一些隐藏的行和组变量,这些在以后 maintained/edited 不容易实现。
可以将以下自定义代码添加到报告中:
Public Shared Function Centile(ByVal items As Object(), ByVal k As Decimal) As Decimal
If items Is Nothing Then
Return Nothing
End If
Dim counter as Decimal = items.Length
If counter = 0 Then
Return 0
End If
System.Array.Sort(items)
Dim Position As Decimal = (k * (counter - 1))
Dim FirstIndex As Integer = Floor(Position)
Dim SecondIndex As Integer = Ceiling(Position)
Dim Remainder As Decimal = Position - FirstIndex
Dim FirstValue As Integer = items(FirstIndex)
Dim SecondValue As Integer = items(SecondIndex)
Return (FirstValue + (Remainder * (SecondValue - FirstValue)))
End Function
可以在表达式中使用 lookupset()
调用,如下所示:
=Code.Centile(lookupset(Fields!ContractName.Value, Fields!ContractName.Value, Fields!Value.Value, "DS_Centile_LKP"), 0.95)
它通过查找 ContractName 字段来回调自身以从同一数据集中获取值。 lookupset()
returns 一个要在此函数中排序的数组,而不是到处都是变量和东西 - 这是显示值的 tablix 文本框中的一个简单函数。
它还允许您使用不同的百分位值 - 在上面的示例中它是第 95 个,所以 0.95。
我们需要根据共享数据集计算 SSRS 报告中的百分位数(第 95 位和第 99 位),该共享数据集 return 按 15 分钟间隔聚合数据。百分位数需要针对整个一天,但根据合约。
为了论证,假设这是我们的数据:
select
'Test' as [ContractName],
1 as [Value]
union all
select
'Test' as [ContractName],
3 as [Value]
union all
select
'Test' as [ContractName],
4 as [Value]
union all
select
'Test' as [ContractName],
6 as [Value]
union all
select
'Test' as [ContractName],
7 as [Value]
union all
select
'Test' as [ContractName],
36 as [Value]
union all
select
'Test' as [ContractName],
56 as [Value]
union all
select
'Test' as [ContractName],
798 as [Value]
union all
select
'Test' as [ContractName],
324 as [Value]
union all
select
'Test' as [ContractName],
456 as [Value]
union all
select
'Test' as [ContractName],
657 as [Value]
union all
select
'Test' as [ContractName],
658 as [Value]
这几乎已排序(我创建它时),但数据本身不会在实际应用程序中。
我需要能够在不更改 SQL 的情况下从此数据集中获取百分位数,因为它是用于合同报告的共享数据集,无法更改。共享数据集用于确保整套报告的一致性。因此,解决方案必须在最终报告输出的 tablix 中。
我查看了 SSRS expression - query from dataset, with group and noticed that it has the same basic usage as this Find the median of a calculated field in SSRS 2012, which comes from https://blogs.msdn.microsoft.com/robertbruckner/2008/07/21/using-group-variables-in-reporting-services-2008-for-custom-aggregation/ 并且需要一些隐藏的行和组变量,这些在以后 maintained/edited 不容易实现。
可以将以下自定义代码添加到报告中:
Public Shared Function Centile(ByVal items As Object(), ByVal k As Decimal) As Decimal
If items Is Nothing Then
Return Nothing
End If
Dim counter as Decimal = items.Length
If counter = 0 Then
Return 0
End If
System.Array.Sort(items)
Dim Position As Decimal = (k * (counter - 1))
Dim FirstIndex As Integer = Floor(Position)
Dim SecondIndex As Integer = Ceiling(Position)
Dim Remainder As Decimal = Position - FirstIndex
Dim FirstValue As Integer = items(FirstIndex)
Dim SecondValue As Integer = items(SecondIndex)
Return (FirstValue + (Remainder * (SecondValue - FirstValue)))
End Function
可以在表达式中使用 lookupset()
调用,如下所示:
=Code.Centile(lookupset(Fields!ContractName.Value, Fields!ContractName.Value, Fields!Value.Value, "DS_Centile_LKP"), 0.95)
它通过查找 ContractName 字段来回调自身以从同一数据集中获取值。 lookupset()
returns 一个要在此函数中排序的数组,而不是到处都是变量和东西 - 这是显示值的 tablix 文本框中的一个简单函数。
它还允许您使用不同的百分位值 - 在上面的示例中它是第 95 个,所以 0.95。