我有一个包含日期和员工编号的登录表。我需要的是计算从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以便我得到我想要的内容。
答案 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 BY
和HAVING
子句中使用别名的原因是自然查询处理顺序,即:
FROM
ON
OUTER
WHERE
GROUP BY
CUBE
| ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
您可以看到SELECT
位于GROUP BY
之后,并且您正在SELECT
语句中创建别名,从而使其在GROUP BY
中无法使用。