带SUM的SQL聚合函数(CASE

时间:2014-01-31 22:59:21

标签: tsql sum case aggregate

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

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无法执行聚合   对包含聚合或子查询的表达式起作用。

4 个答案:

答案 0 :(得分: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 

在您的功能中,您可以选择,更新,完成所需的一切......

希望这有效......

...问候

答案 1 :(得分:0)

将您的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 

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

答案 2 :(得分:0)

与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 

答案 3 :(得分:0)

以下是在执行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