【问题标题】:SQL - Cant use aggregate of subquery in Group clauseSQL - 不能在组子句中使用子查询的聚合
【发布时间】:2016-01-26 21:34:27
【问题描述】:

我尝试在以下查询中按 [DueDate] 分组,但该日期可能因设置而异。无论如何我可以完成这项工作吗?

SELECT
(
    SELECT CASE 
    WHEN (SELECT TOP 1 [SiconCFMSetting].[SettingValue] FROM [SiconCFMSetting] WHERE [SiconCFMSetting].[SettingName]='UseAverageTimeToPay') = 'True'
    THEN ISNULL([SiconCFMForecastDate].[ForecastDate],DATEADD([DD],[SiconCFMSLCustomerAverageTimeToPayView].[Days],[SLPostedCustomerTran].[TransactionDate]))
    ELSE ISNULL([SiconCFMForecastDate].[ForecastDate],[SLPostedCustomerTran].[DueDate])
    END
) AS [DueDate],
SUM([SLPostedCustomerTran].[SalControlValueInBaseCurrency]) AS [Value]
FROM        [SLPostedCustomerTran]
INNER JOIN  [SLCustomerAccount]
ON          [SLCustomerAccount].[SLCustomerAccountID]
=           [SLPostedCustomerTran].[SLCustomerAccountID]
INNER JOIN  [SiconCFMSLCustomerAverageTimeToPayView]
ON          [SiconCFMSLCustomerAverageTimeToPayView].[SLCustomerAccountID]
=           [SLCustomerAccount].[SLCustomerAccountID]
LEFT JOIN   [SiconCFMForecastDate]
ON          [SiconCFMForecastDate].[ForecastDateForeignID]
=           [SLPostedCustomerTran].[SLPostedCustomerTranID]
AND         [SiconCFMForecastDate].[Deleted]=0
AND         [SiconCFMForecastDate].[ForecastDateSource]='SLPostedCustomerTran'
WHERE       ([SLPostedCustomerTran].[SYSTraderTranTypeID]=4 OR [SLPostedCustomerTran].[SYSTraderTranTypeID]=5)
AND         [SLPostedCustomerTran].[SalControlValueInBaseCurrency] <> 0
GROUP BY    
    CASE 
    WHEN (SELECT TOP 1 [SiconCFMSetting].[SettingValue] FROM [SiconCFMSetting] WHERE [SiconCFMSetting].[SettingName]='UseAverageTimeToPay') = 'True'
    THEN ISNULL([SiconCFMForecastDate].[ForecastDate],DATEADD([DD],[SiconCFMSLCustomerAverageTimeToPayView].[Days],[SLPostedCustomerTran].[TransactionDate]))
    ELSE ISNULL([SiconCFMForecastDate].[ForecastDate],[SLPostedCustomerTran].[DueDate])
    END

错误: 消息 144,第 15 级,状态 1,第 26 行 不能在用于 GROUP BY 子句的 group by 列表的表达式中使用聚合或子查询。

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    在外部查询中进行聚合。你可以这样做

    with cte as
    (
    SELECT
    (
        SELECT CASE 
        WHEN (SELECT TOP 1 [SiconCFMSetting].[SettingValue] FROM [SiconCFMSetting] WHERE [SiconCFMSetting].[SettingName]='UseAverageTimeToPay') = 'True'
        THEN ISNULL([SiconCFMForecastDate].[ForecastDate],DATEADD([DD],[SiconCFMSLCustomerAverageTimeToPayView].[Days],[SLPostedCustomerTran].[TransactionDate]))
        ELSE ISNULL([SiconCFMForecastDate].[ForecastDate],[SLPostedCustomerTran].[DueDate])
        END
    ) AS [DueDate],
    [SLPostedCustomerTran].[SalControlValueInBaseCurrency] AS [Value]
    FROM        [SLPostedCustomerTran]
    INNER JOIN  [SLCustomerAccount]
    ON          [SLCustomerAccount].[SLCustomerAccountID]
    =           [SLPostedCustomerTran].[SLCustomerAccountID]
    INNER JOIN  [SiconCFMSLCustomerAverageTimeToPayView]
    ON          [SiconCFMSLCustomerAverageTimeToPayView].[SLCustomerAccountID]
    =           [SLCustomerAccount].[SLCustomerAccountID]
    LEFT JOIN   [SiconCFMForecastDate]
    ON          [SiconCFMForecastDate].[ForecastDateForeignID]
    =           [SLPostedCustomerTran].[SLPostedCustomerTranID]
    AND         [SiconCFMForecastDate].[Deleted]=0
    AND         [SiconCFMForecastDate].[ForecastDateSource]='SLPostedCustomerTran'
    WHERE       ([SLPostedCustomerTran].[SYSTraderTranTypeID]=4 OR [SLPostedCustomerTran].[SYSTraderTranTypeID]=5)
    AND         [SLPostedCustomerTran].[SalControlValueInBaseCurrency] <> 0
    )
    select DueDate,sum(Value)
    from cte 
    group by DueDate
    

    要在单个查询中执行此操作,请使用 OUTER APPLY

    SELECT OA.[DueDate],
           Sum([SLPostedCustomerTran].[SalControlValueInBaseCurrency]) AS [Value]
    FROM   [SLPostedCustomerTran]
           INNER JOIN [SLCustomerAccount]
                   ON [SLCustomerAccount].[SLCustomerAccountID] = [SLPostedCustomerTran].[SLCustomerAccountID]
           INNER JOIN [SiconCFMSLCustomerAverageTimeToPayView]
                   ON [SiconCFMSLCustomerAverageTimeToPayView].[SLCustomerAccountID] = [SLCustomerAccount].[SLCustomerAccountID]
           LEFT JOIN [SiconCFMForecastDate]
                  ON [SiconCFMForecastDate].[ForecastDateForeignID] = [SLPostedCustomerTran].[SLPostedCustomerTranID]
                     AND [SiconCFMForecastDate].[Deleted] = 0
                     AND [SiconCFMForecastDate].[ForecastDateSource] = 'SLPostedCustomerTran'
           OUTER apply (SELECT CASE
                                 WHEN (SELECT TOP 1 [SiconCFMSetting].[SettingValue]
                                       FROM   [SiconCFMSetting]
                                       WHERE  [SiconCFMSetting].[SettingName] = 'UseAverageTimeToPay') = 'True' THEN Isnull([SiconCFMForecastDate].[ForecastDate], Dateadd([DD], [SiconCFMSLCustomerAverageTimeToPayView].[Days], [SLPostedCustomerTran].[TransactionDate]))
                                 ELSE Isnull([SiconCFMForecastDate].[ForecastDate], [SLPostedCustomerTran].[DueDate])
                               END) OA ([DueDate])
    WHERE  ( [SLPostedCustomerTran].[SYSTraderTranTypeID] = 4
              OR [SLPostedCustomerTran].[SYSTraderTranTypeID] = 5 )
           AND [SLPostedCustomerTran].[SalControlValueInBaseCurrency] <> 0 
    

    【讨论】:

    • 谢谢,我现在试试!
    • 这就是诀窍!我会尽快接受答案
    • @WraithNath 检查另一种方式
    • 谢谢,我使用外部 SELECT 进行了一些测试,您所做的 WITH 语句的时间非常相似。 OUTER APPLY 会更快吗?是什么让你也想这样尝试?
    猜你喜欢
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2021-09-13
    相关资源
    最近更新 更多