2014-01-31 5 views
0

Я понимаю, что я не могу выполнить подзапрос в агрегированной функции. Как я могу обойти эту проблему. Мне нужно уметь вычислять текущий финансовый период из другой таблицы и передавать ее мой запрос. Я пытаюсь вычислить месяц до даты чисел. Любые идеи оценили.SQL AGGREGATE FUNCTION WITH SUM (CASE

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 

Здесь ошибка

Msg 130, Level 15, State 1, Line 4 Невозможно выполнить агрегатный функция в выражении, содержащем агрегат или подзапрос.

ответ

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 

В функции, вы можете выбрать, обновлять, делать все, что нужно ...

Надеется, что это работает ...

с уважением ...

+0

Работает как очарование, спасибо! –

0

Перемещайте отборное заявление вниз в соединение, а затем подвести его:

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 

У меня нет вашей схемы, поэтому я не могу проверить, но это будет по этим линиям.

0

Аналогичная концепция ответа Дэмиена: вы также можете выполнить вывод подзапроса, а затем суммировать результат.

Этот ответ отличается тем, что все поля, необходимые для создания желаемой группировки, включены в вывод внутреннего запроса, поэтому конечный вывод должен быть одинаковым.

Если вы предпочитаете, вы также можете взять все внутри блока 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 
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