【问题标题】:how to get a distinct value and then group by it?如何获得一个独特的价值,然后按它分组?
【发布时间】:2016-06-13 17:43:46
【问题描述】:

我试图通过 SSRS 而不是查询获得不同的记录,然后根据不同的值对数据求和。我正在 SSRS 数据集中执行存储过程来获取数据。下面是proc的结果:

Company ProductID PayeeID PayeeName GroupID Profit
ABC     123       1       Brenda     1a      $30
ABC     123       1       Brenda     1a      $30
ABC     123       1       Brenda     1b      $30
ABC     456       2       Diana      2a      $45
ABC     456       2       Diana      2a      $45
ABC     789       3       Jonathan   3a      $23
ABC     789       3       Jonathan   3a      $23
ABC     789       3       Jonathan   3b      $23
ABC     789       3       Jonathan   3b      $23

我需要做的是对唯一的公司、产品、收款人而不是 groupID 进行分组和总利润。如您所见,存在重复的组 ID。我想要清楚的记录。我已经在 SSRS 中设置了所有分组,但不知道如何区分 GroupID,所以我的结果在 SSRS 中显示如下:

Company ProductID PayeeID PayeeName Profit
ABC     123       1       Brenda    $90     =(1a+1a+1b)
ABC     456       2       Diana     $90
ABC     789       3       Jonathan  $92

**不应重复 GroupID 的 SUM 值

我想要什么:

Company ProductID PayeeID PayeeName Profit
ABC     123       1       Brenda    $60     =(1a+1b)
ABC     456       2       Diana     $45
ABC     789       3       Jonathan  $46

**不对重复值求和

关于如何在 SSRS 中而不是在查询级别执行此操作的任何想法?我不想在查询级别上的原因是因为我必须创建一个表,执行 proc 并将其数据存储在我创建的表中。将来,如果修改了存储的 proc 结构,那么我将不得不在两个地方进行修改以使报告工作。任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: sql sql-server reporting-services ssrs-2008


    【解决方案1】:

    您可以尝试以下方法:

    SELECT Company, ProductID, PayeeID, PayeeName, SUM(Profit) as Profit
    FROM (SELECT DISTINCT * FROM Table_1) as t
    GROUP BY Company, ProductID, PayeeID, PayeeName;
    

    【讨论】:

      【解决方案2】:

      1) 如果可以接受,我会在同一个存储过程中计算这个新列的值:

      SELECT a.*, 
          SUM(CASE WHEN RowNum = 1 THEN Profit END)
          OVER(PARTITION BY a.Company/*or CompanyID ?*/, ProductID, PayeeID) AS SumOfProfit
      FROM (
          SELECT ..., -- Plus one more column
              ROW_NUMBER() OVER(PARTITION BY a.Company/*or CompanyID ?*/, ProductID, PayeeID, GroupID ORDER BY @@SPID) AS RowNum
          FROM ... final query from stored procedure ...
          ....
      ) a
      

      基本上,这会在原始数据集 (!) 中添加一个新列 (SumOfProfit)

      Company ProductID PayeeID PayeeName GroupID Profit SumOfProfit
      ABC     123       1       Brenda     1a      $30   60
      ABC     123       1       Brenda     1a      $30   60
      ABC     123       1       Brenda     1b      $30   60
      ABC     456       2       Diana      2a      $45   ...
      ABC     456       2       Diana      2a      $45
      ABC     789       3       Jonathan   3a      $23
      ABC     789       3       Jonathan   3a      $23
      ABC     789       3       Jonathan   3b      $23
      ABC     789       3       Jonathan   3b      $23
      

      2) 第二种解决方案是将(何时)存储过程转换为用户定义的函数

      • 多步 UDF 函数(如果它有两行或多行)或
      • 内联 UDF 函数(如果它只有一行;注意:有时可以将多行存储过程转换为 {inline|single line} 函数)

      我会改变存储过程:

      ALTER PROCEDURE ...
      AS
      BEGIN
          SELECT f....
          FROM dbo.UserDefinedFunction(...) f
          -- ORDER BY ... ?
      END
      

      对于这份报告,我将使用(作为数据源)以下查询/存储过程:

      SELECT s.Company, s.ProductID, s.PayeeID, SUM(Profit) AS SumOfProfit
      FROM (
          SELECT DISTINCT f.Company, f.ProductID, f.PayeeID, f.GroupID, f.Profit
          FROM dbo.UserDefinedFunction(...) f
      ) s
      GROUP BY s.Company, s.ProductID, s.PayeeID
      

      3) 当然,如果解决方案 1 和 2 不适用并且if initial stored procedure don't include insert into another table,那么对于第二个报告我们可以重用第一个存储过程(我不喜欢这种方法):

      CREATE TABLE #Results (
          Company ...,
          ProductID INT,
          PayeeID INT,
          ...
      )
      INSERT #Results (...)
      EXEC dbo.FirstStoredProcedure (...)
      -- and then 
      SELECT s.Company, s.ProductID, s.PayeeID, SUM(Profit) AS SumOfProfit
      FROM (
          SELECT DISTINCT f.Company, f.ProductID, f.PayeeID, f.GroupID, f.Profit
          FROM #Results f
      ) s
      GROUP BY s.Company, s.ProductID, s.PayeeID
      

      【讨论】:

      • 注意:我知道这不是 SSRS 唯一的解决方案。
      【解决方案3】:

      我在这里使用的是纯 SSRS 解决方案,但它非常丑陋且不必要的复杂。这个解决方案是为了好玩,所以我建议对大型数据集使用这种方法,我强烈推荐 T-SQL 级别的解决方案。

      根据您发布的数据集,我创建了以下 tablix:

      我使用“列可见性”窗口隐藏了最后一列(详细信息列)。

      使用自定义代码,您可以使用 VB 代码扩展 SSRS 函数的功能。转到Report 菜单/Report properties... 切换到Code 选项卡,然后将以下代码放入文本区域。

      Public Function MySum(ByVal groups as Object(), ByVal values as Object()) As Integer
      Dim found_groups As System.Collections.ArrayList=New System.Collections.ArrayList()
      Dim n as Integer
      Dim sum as Integer = 0
      For n = 0 To groups.Length-1
          If not found_groups.Contains(groups(n)) Then
              found_groups.Add(groups(n))
              sum = sum + values(n)
          End If
      Next
      Return sum
      End Function
      

      在选定的单元格中(查看 tablix 屏幕截图)我使用了这个表达式:

      =Code.MySum(Lookupset(
      Fields!ProductID.Value &"-"&
      Fields!PayeeID.Value &"-",
      Fields!ProductID.Value &"-"&
      Fields!PayeeID.Value &"-",
      CStr(Fields!GroupID.Value),
      "DataSet1"
      ),
      Lookupset(
      Fields!ProductID.Value &"-"&
      Fields!PayeeID.Value &"-",
      Fields!ProductID.Value &"-"&
      Fields!PayeeID.Value &"-",
      CStr(Fields!Profit.Value),
      "DataSet1"
      ))
      

      注意 MySum() 函数将两个数组作为参数并返回一个整数,即给定组中 Profit 值的总和。

      它预览如下内容:

      注意:此解决方案是基于提供的数据集构建的 您的问题,如果数据结构发生变化,它将无法正常工作。

      如果这有帮助,请告诉我。

      【讨论】:

        猜你喜欢
        • 2015-12-13
        • 2021-01-21
        • 1970-01-01
        • 2011-03-26
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 2022-01-13
        • 2019-01-14
        相关资源
        最近更新 更多