【问题标题】:SQL AGGREGATE FUNCTION WITH SUM(CASESQL 聚合函数与 SUM(CASE
【发布时间】:2014-02-24 19:54:09
【问题描述】:

我了解我无法在聚合函数中执行子查询。我该如何解决这个问题。我需要能够从另一个表中找出当前的会计期间并将其传递给我的查询。我正在尝试计算月至今的数字。任何想法表示赞赏。

SELECT SUM(CASE
             WHEN CRMBNB_DATE_1.AccountingFiscalPeriod = 
                            /*Problem subquery*/
                            (SELECT AccountingFiscalPeriod
                            FROM   crmbnb_date
                            WHERE  DAY = cast(CONVERT(VARCHAR(10), getdate(), 110) AS DATE))
                  AND ( CRMBNB_DATE_1.FiscalYear = YEAR(DATEADD(mm, -3, GETDATE())) ) THEN BL_Amount
             ELSE 0
           END) AS [MTD Billing]
FROM   CRMBNB_BILLINGS
       INNER JOIN CRMBNB_DATE AS CRMBNB_DATE_1
         ON CRMBNB_BILLINGS.InvoiceDate = CRMBNB_DATE_1.Day
       INNER JOIN CRMBNB_EMPLOYEE AS CRMBNB_EMPLOYEE_1
         ON CRMBNB_BILLINGS.BL_EmployeeNo = CRMBNB_EMPLOYEE_1.EmployeeNo
       INNER JOIN CRMBNB_SALESREGION AS CRMBNB_SALESREGION_1
         ON CRMBNB_EMPLOYEE_1.Employee_Region = CRMBNB_SALESREGION_1.Region
WHERE  ( CRMBNB_SALESREGION_1.Area IN ( 'OGS' ) )
--AND (CRMBNB_DATE_1.AccountingFiscalPeriod IN (10)) AND (CRMBNB_DATE_1.FiscalYear IN (2013)) 
--AND (CRMBNB_BILLINGS.BL_ProductLine IN (@PRODUCTLINE))
GROUP  BY CRMBNB_SALESREGION_1.Area,
          CRMBNB_SALESREGION_1.Region,
          CRMBNB_DATE_1.AccountingFiscalPeriod,
          CRMBNB_DATE_1.FiscalYear,
          CRMBNB_SALESREGION_1.RegionDesc,
          CRMBNB_BILLINGS.BL_ProductLine 

这是错误

消息 130,级别 15,状态 1,行 4 无法执行聚合 包含聚合或子查询的表达式上的函数。

【问题讨论】:

    标签: tsql sum case aggregate


    【解决方案1】:

    您可以使用函数代替“子查询”,例如:

        SELECT SUM(CASE
             WHEN CRMBNB_DATE_1.AccountingFiscalPeriod = 
                          **Fn_XXX()** THEN BL_Amount
             ELSE 0
           END) AS [MTD Billing]
     FROM   CRMBNB_BILLINGS
       INNER JOIN CRMBNB_DATE AS CRMBNB_DATE_1
         ON CRMBNB_BILLINGS.InvoiceDate = CRMBNB_DATE_1.Day
       INNER JOIN CRMBNB_EMPLOYEE AS CRMBNB_EMPLOYEE_1
         ON CRMBNB_BILLINGS.BL_EmployeeNo = CRMBNB_EMPLOYEE_1.EmployeeNo
       INNER JOIN CRMBNB_SALESREGION AS CRMBNB_SALESREGION_1
         ON CRMBNB_EMPLOYEE_1.Employee_Region = CRMBNB_SALESREGION_1.Region
        WHERE  ( CRMBNB_SALESREGION_1.Area IN ( 'OGS' ) )
      --AND (CRMBNB_DATE_1.AccountingFiscalPeriod IN (10)) AND (CRMBNB_DATE_1.FiscalYear IN (2013)) 
         --AND (CRMBNB_BILLINGS.BL_ProductLine IN (@PRODUCTLINE))
             GROUP  BY CRMBNB_SALESREGION_1.Area,
          CRMBNB_SALESREGION_1.Region,
          CRMBNB_DATE_1.AccountingFiscalPeriod,
          CRMBNB_DATE_1.FiscalYear,
          CRMBNB_SALESREGION_1.RegionDesc,
          CRMBNB_BILLINGS.BL_ProductLine 
    

    在你的函数中,你可以选择、更新、做你需要的一切......

    希望这行得通...

    问候...

    【讨论】:

      【解决方案2】:

      将您的 select 语句向下移动到一个连接中,然后对其求和:

      SELECT SUM(temp_result)
      
      FROM SELECT
               WHEN CRMBNB_DATE_1.AccountingFiscalPeriod = 
                            (SELECT AccountingFiscalPeriod
                              FROM   crmbnb_date
                              WHERE  DAY = cast(CONVERT(VARCHAR(10), getdate(), 110) AS DATE))
                    AND ( CRMBNB_DATE_1.FiscalYear = YEAR(DATEADD(mm, -3, GETDATE())) ) THEN BL_Amount
               ELSE 0
             END) AS temp_result
         FROM   CRMBNB_BILLINGS
         INNER JOIN CRMBNB_DATE AS CRMBNB_DATE_1
           ON CRMBNB_BILLINGS.InvoiceDate = CRMBNB_DATE_1.Day
         INNER JOIN CRMBNB_EMPLOYEE AS CRMBNB_EMPLOYEE_1
           ON CRMBNB_BILLINGS.BL_EmployeeNo = CRMBNB_EMPLOYEE_1.EmployeeNo
         INNER JOIN CRMBNB_SALESREGION AS CRMBNB_SALESREGION_1
           ON CRMBNB_EMPLOYEE_1.Employee_Region = CRMBNB_SALESREGION_1.Region
      WHERE  ( CRMBNB_SALESREGION_1.Area IN ( 'OGS' ) )
      --AND (CRMBNB_DATE_1.AccountingFiscalPeriod IN (10)) AND (CRMBNB_DATE_1.FiscalYear IN (2013)) 
      --AND (CRMBNB_BILLINGS.BL_ProductLine IN (@PRODUCTLINE))
      GROUP  BY CRMBNB_SALESREGION_1.Area,
            CRMBNB_SALESREGION_1.Region,
            CRMBNB_DATE_1.AccountingFiscalPeriod,
            CRMBNB_DATE_1.FiscalYear,
            CRMBNB_SALESREGION_1.RegionDesc,
            CRMBNB_BILLINGS.BL_ProductLine 
      

      我没有你的架构,所以我无法测试,但它会沿着这些思路。

      【讨论】:

        【解决方案3】:

        与 Damien 的回答类似的概念:您也可以暂存子查询输出,然后对结果求和。

        此答案的不同之处在于生成所需分组所需的所有字段都包含在内部查询的输出中,因此最终输出应该相同。

        如果您愿意,也可以将下面 FROM () 块中的所有内容插入到表变量或临时表中。这将使最终的查询更加简单。

        SELECT SUM(results.[MTD billing])
        FROM (
        
          /* Subquery to produce a staged result set */
          SELECT  CRMBNB_SALESREGION_1.Area,
                  CRMBNB_SALESREGION_1.Region,
                  CRMBNB_DATE_1.AccountingFiscalPeriod,
                  CRMBNB_DATE_1.FiscalYear,
                  CRMBNB_SALESREGION_1.RegionDesc,
                  CRMBNB_BILLINGS.BL_ProductLine,
                  (CASE
                       WHEN CRMBNB_DATE_1.AccountingFiscalPeriod = 
                                      /*Problem subquery*/
                                      (SELECT AccountingFiscalPeriod
                                        FROM   crmbnb_date
                                      WHERE  DAY = cast(CONVERT(VARCHAR(10), getdate(), 110) AS DATE))
                            AND ( CRMBNB_DATE_1.FiscalYear = YEAR(DATEADD(mm, -3, GETDATE())) ) THEN BL_Amount
                       ELSE 0
                     END) AS [MTD Billing]
          FROM   CRMBNB_BILLINGS
                 INNER JOIN CRMBNB_DATE AS CRMBNB_DATE_1
                   ON CRMBNB_BILLINGS.InvoiceDate = CRMBNB_DATE_1.Day
                 INNER JOIN CRMBNB_EMPLOYEE AS CRMBNB_EMPLOYEE_1
                   ON CRMBNB_BILLINGS.BL_EmployeeNo = CRMBNB_EMPLOYEE_1.EmployeeNo
                 INNER JOIN CRMBNB_SALESREGION AS CRMBNB_SALESREGION_1
                   ON CRMBNB_EMPLOYEE_1.Employee_Region = CRMBNB_SALESREGION_1.Region
          WHERE  ( CRMBNB_SALESREGION_1.Area IN ( 'OGS' ) )
          /* Staging subquery ends here */
        
        ) results
        GROUP  BY results.Area,
                  results.Region,
                  results.AccountingFiscalPeriod,
                  results.FiscalYear,
                  results.RegionDesc,
                  results.BL_ProductLine 
        

        【讨论】:

          【解决方案4】:

          这是在执行 SUM() 之前首先将结果存储在表变量中的示例。

          这种方法减少了子查询的嵌套,但它使 SQL 优化器的一些决策脱离了。我无法保证这种方法的性能相同。

          这样分离的一个好处是,如果您想从相同的数据生成多个结果集(例如,如果您还想生成平均值,或者想显示不同的分组级别)。

          DECLARE @RESULTS TABLE (
            Area NVARCHAR(MAX),
            Region NVARCHAR(MAX),
            AccountingFiscalPeriod NVARCHAR(MAX),
            FiscalYear NVARCHAR(MAX),
            RegionDesc NVARCHAR(MAX),
            ProductLine NVARCHAR(MAX),
            [MTD Billing] NUMERIC(19,4)
          )
          
          INSERT INTO @RESULTS
          SELECT  CRMBNB_SALESREGION_1.Area,
                  CRMBNB_SALESREGION_1.Region,
                  CRMBNB_DATE_1.AccountingFiscalPeriod,
                  CRMBNB_DATE_1.FiscalYear,
                  CRMBNB_SALESREGION_1.RegionDesc,
                  CRMBNB_BILLINGS.BL_ProductLine,
                  (CASE
                       WHEN CRMBNB_DATE_1.AccountingFiscalPeriod = 
                                      /*Problem subquery*/
                                      (SELECT AccountingFiscalPeriod
                                        FROM   crmbnb_date
                                      WHERE  DAY = cast(CONVERT(VARCHAR(10), getdate(), 110) AS DATE))
                            AND ( CRMBNB_DATE_1.FiscalYear = YEAR(DATEADD(mm, -3, GETDATE())) ) THEN BL_Amount
                       ELSE 0
                     END) AS [MTD Billing]
          FROM   CRMBNB_BILLINGS
                 INNER JOIN CRMBNB_DATE AS CRMBNB_DATE_1
                   ON CRMBNB_BILLINGS.InvoiceDate = CRMBNB_DATE_1.Day
                 INNER JOIN CRMBNB_EMPLOYEE AS CRMBNB_EMPLOYEE_1
                   ON CRMBNB_BILLINGS.BL_EmployeeNo = CRMBNB_EMPLOYEE_1.EmployeeNo
                 INNER JOIN CRMBNB_SALESREGION AS CRMBNB_SALESREGION_1
                   ON CRMBNB_EMPLOYEE_1.Employee_Region = CRMBNB_SALESREGION_1.Region
          WHERE  ( CRMBNB_SALESREGION_1.Area IN ( 'OGS' ) )
          
          SELECT SUM([MTD billing])
          FROM @RESULTS
          GROUP  BY Area,
                    Region,
                    AccountingFiscalPeriod,
                    FiscalYear,
                    RegionDesc,
                    BL_ProductLine 
          

          【讨论】:

            猜你喜欢
            • 2021-05-08
            • 2020-08-05
            • 1970-01-01
            • 2011-09-27
            • 2018-04-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-11-14
            相关资源
            最近更新 更多