条件引用父查询的SQL Server聚合子查询错误

时间:2017-09-22 16:08:27

标签: sql-server tsql subquery aggregate-functions

我正在尝试在select语句中为以下代码添加聚合子查询。

DECLARE @Date1 Date
DECLARE @Date2 Date

SET @Date1 = '2017-01-01'
SET @Date2 = '2017-03-01'

SELECT  
    p.PracticeName [Practice Name],
    dbo.getFormattedName(l.Userid) [User Name],
    MAX(EventDate) [Last Activity],
    COUNT(*) [Activity Count],
    (SELECT COUNT(*)
     FROM UserEvent EVT (NOLOCK) 
     WHERE EVT.EventTypeID = 1 
       AND EVT.UserID = au.userID 
       AND EVT.EventDate >= @Date1 
       AND EVT.EventDate <= DATEADD(DAY, 1, @Date2)
    GROUP BY 
        au.userID) [Login Count]
FROM    
    dbo.AudLog l (NOLOCK) 
JOIN
    Appuser au (NOLOCK) ON l.UserID = au.UserID
JOIN
    Practice p (NOLOCK) ON au.PracticeID = p.PracticeID
WHERE   
    l.EnvironmentID = 1
    AND EventDate >= @Date1
    AND EventDate <= DATEADD(DAY,1,@Date2)
GROUP BY    
    p.PracticeName,
    dbo.getFormattedName(l.Userid)
ORDER BY    
    p.PracticeName,
    dbo.getFormattedName(l.Userid)

我收到以下错误:

  

列'Appuser.UserID'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

我不明白为什么该错误适用于我的子查询,因为我没有选择AppUser.UserID,我只是用作条件的参考来将子查询与父查询对齐。此外,它确实位于子查询中的GROUP BY语句中。

我引用了this question,但根据解释,我认为我的查询会有效。

任何帮助表示感谢。

4 个答案:

答案 0 :(得分:0)

如果您加入某个字段,它将出现在作为联接一部分的中间数据集中。即使它不在您的选择列表中,您也需要将其视为列表的一部分。

如果你真的认为这不是问题,那么你可以将它添加到你的group by子句中,并仍然得到你想要的结果。

答案 1 :(得分:0)

错误未引用您的子查询。

主查询的select子句中的以下行dbo.ch_getFormattedProviderName(l.Userid)是问题所在。

您在select语句中使用函数调用dbo.ch_getFormattedProviderName(l.Userid),但是您在group by子句中按照不同的函数dbo.getFormattedName(l.Userid)进行分组。

将功能 dbo.ch_getFormattedProviderName 更改为 dbo.getFormattedName ,反之亦然。

答案 2 :(得分:0)

您引用的问题不同,因为外部查询中没有需要GROUP BY的聚合函数。

当您使用相关子查询(EVT.UserID = au.userID)时,外部查询列引用(在本例中为au.userID)现在是外部选择中列的一部分(因为它是子查询所必需的。)

简单的解决方法是将au.userID列添加到外部组。

答案 3 :(得分:0)

这不是你问题的答案,但是。我想在您的查询中提及一些内容。

  • 避免使用标量函数。尽量不要使用它们。它们几乎没有使用它们的好例子。如果您希望封装逻辑,则只需使用表值函数。标量函数是性能杀手,特别是如果你需要通过它们进行过滤。它们不会被编入索引,它们将在每一行上执行。
  • 我个人没有看到这种内联子查询优于普通JOIN内联查询的情况。但是当表现更差时,我看到了很多相反的情况。您始终可以使用JOIN(SELECT ...)
  • 重新编写此类查询
  • NOLOCKs ......他们不是很推荐。如果你有锁定问题,那么通过使用索引/重新设计Technics解决它们。最好解决问题的根源而不是解决方法。