带有GROUP,DISTINCT和HAVING的T-SQL上的语法错误

时间:2015-10-26 19:42:18

标签: sql-server tsql group-by

我有一个包含日期和员工编号的登录表。我需要的是计算从2014年开始登录的每个月和每年有多少独特的员工登录。

这是我能够得到的:

SELECT YEAR(Date) AS 'Year', MONTH(Date) AS 'Month', COUNT(DISTINCT EmpID) AS EmpCount
FROM [Logins].[dbo].[tblPortalLog]
GROUP BY 'Year', 'Month'
having 'Year' >= '2014';

...但我收到错误:“每个GROUP BY表达式必须包含至少一个不是外部引用的列。”

我搜索了该错误,但我仍然无法弄清楚如何更改SQL以便我得到我想要的内容。

3 个答案:

答案 0 :(得分:1)

您应该在别名周围使用双引号或[]而不是单引号(编辑:在having子句中)。单引号表示字符串值。另外,为了便于携带,您应该使用实际表达式而不是组中的别名。

SELECT YEAR(Date) AS [Year], MONTH(Date) AS [Month], COUNT(DISTINCT EmpID) AS EmpCount 
FROM [Logins].[dbo].[tblPortalLog] 
GROUP BY YEAR(Date), MONTH(Date) 
HAVING YEAR(Date) >= '2014'

另外,如另一个答案所述,您的情况应该在WHERE条款而不是HAVING。此外,比较原始日期很可能更快。

SELECT YEAR(Date) AS [Year], MONTH(Date) AS [Month], COUNT(DISTINCT EmpID) AS EmpCount 
FROM [Logins].[dbo].[tblPortalLog] 
WHERE Date >= '20140101'
GROUP BY YEAR(Date), MONTH(Date) 

答案 1 :(得分:1)

首先,使用“where子句”仅处理您需要的数据 然后,当使用“group by clause”时,不能引用出现在“select子句”中的列别名。你必须重复这个公式。在这种情况下,公式为“YEAR(Date)”。

SELECT  Year     = YEAR([Date]), 
        Month    = MONTH([Date]), 
        EmpCount = COUNT(DISTINCT EmpID)
FROM [Logins].[dbo].[tblPortalLog] 
WHERE YEAR([Date]) >= 2014
GROUP BY    YEAR([Date]), 
            MONTH([Date]) 

N.B:我在日期附近添加了方括号,因为它是一个保留的世界。

答案 2 :(得分:1)

您的查询不正确,首先。

您不是按YEAR(Date)MONTH(Date)分组,而是按字符'Year''Month'进行分组。这就是您收到错误的原因。你是如何解决的?

非常简单。这是正确的查询:

SELECT YEAR(Date) AS [Year], MONTH(Date) AS [Month], COUNT(DISTINCT [EmpID]) AS [EmpCount]
FROM [Logins].[dbo].[tblPortalLog]
GROUP BY YEAR(Date), MONTH(Date)
HAVING YEAR(Date) >= '2014';

如果您希望美化并使您的别名可用,您可以使用CROSS APPLY来实现:

SELECT T.[Year], T.[Month], COUNT(DISTINCT [EmpID]) AS [EmpCount]
FROM [Logins].[dbo].[tblPortalLog]
CROSS APPLY (
    SELECT YEAR(Date) AS [Year], MONTH(Date) AS [Month]
    ) AS T
GROUP BY T.[Year], T.[Month]
HAVING T.[Year] >= '2014';

您无法在GROUP BYHAVING子句中使用别名的原因是自然查询处理顺序,即:

  1. FROM
  2. ON
  3. OUTER
  4. WHERE
  5. GROUP BY
  6. CUBE | ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP
  12. 您可以看到SELECT位于GROUP BY之后,并且您正在SELECT语句中创建别名,从而使其在GROUP BY中无法使用。