SQL Server 2015中的查询导致问题
我的问题是:SQL Server 2015中的查询导致问题,sql,sql-server,group-by,Sql,Sql Server,Group By,我的问题是: select distinct e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date) AttDate, PunchTimes = Stuff((Select ', ' + convert(varchar, d.LogDate, 8) from DeviceLogs dl WITH (NoLock)
select distinct
e.EmployeeId, EmployeeCode, EmployeeName,
Cast(d.LogDate as date) AttDate,
PunchTimes = Stuff((Select ', ' + convert(varchar, d.LogDate, 8)
from DeviceLogs dl WITH (NoLock)
where dl.UserId = e.EmployeeId
and cast(dl.LogDate as date) = cast(d.LogDate as date)
for XML path('') ), 1, 2, '')
from
Employees e, DeviceLogs d
where
e.EmployeeId = d.UserId
--and cast(d.LogDate as date) between cast(@FromDate as date) and cast(@ToDate as date)
and cast(d.LogDate as date) between '1-Jun-2019' and '1-Jun-2019'
group by
e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date)
我得到这个错误:
Msg 8120,16级,状态1,第2行
列“DeviceLogs.LogDate”在选择列表中无效,因为它未包含在聚合函数或GROUP BY子句中
您需要将castdl.logdateas date列添加到GROUPBY子句中
更正:误读子查询中的别名;问题是对子查询中使用了d.LogDate的相关引用。给定以下DDL
CREATE TABLE Employees (EmployeeId INT PRIMARY KEY
, EmployeeCode INT
, EmployeeName VARCHAR(255))
CREATE TABLE DeviceLogs (UserId INT FOREIGN KEY REFERENCES dbo.Employees(EmployeeId), LogDate DATETIME)
这项工作:-
select distinct e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date) AttDate,
PunchTimes = Stuff((Select ', ' + convert(varchar, dl.LogDate, 8)
from DeviceLogs dl WITH (NoLock)
where dl.UserId = e.EmployeeId and cast(dl.LogDate as
date) = cast(d.LogDate as date) for XML path('') ),1, 2, '')
from Employees e, DeviceLogs d
where e.EmployeeId = d.UserId
and cast(d.LogDate as date) between '1-Jun-2019' and '1-Jun-2019'
group by e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date)
但最初的问题不是:
select distinct e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date) AttDate,
PunchTimes = Stuff((Select ', ' + convert(varchar, d.LogDate, 8)
from DeviceLogs dl WITH (NoLock)
where dl.UserId = e.EmployeeId and cast(dl.LogDate as
date) = cast(d.LogDate as date) for XML path('') ),1, 2, '')
from Employees e, DeviceLogs d
where e.EmployeeId = d.UserId
and cast(d.LogDate as date) between '1-Jun-2019' and '1-Jun-2019'
group by e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date)
试试这个
select distinct e.EmployeeId, EmployeeCode, EmployeeName, Cast(d.LogDate as date) AttDate,
PunchTimes = Stuff((Select ', ' + convert(varchar, d.LogDate, 8) from DeviceLogs dl WITH (NoLock)
where dl.UserId = e.EmployeeId and cast(dl.LogDate as date) = cast(d.LogDate as date) for XML path('') ),1, 2, '')
from Employees e, DeviceLogs d
where e.EmployeeId = d.UserId
--and cast(d.LogDate as date) between cast(@FromDate as date) and cast(@ToDate as date)
and cast(d.LogDate as date) between '1-Jun-2019' and '1-Jun-2019'
group by e.EmployeeId, EmployeeCode, EmployeeName, AttDate
any aggregate function is not allowed in group by
我建议避免分组方式,而是在子查询中使用select distinct:
select e.*,
stuff( (select ', ' + convert(varchar(255), d.LogDate, 8)
from DeviceLogs dl
where dl.UserId = e.EmployeeId and
cast(dl.LogDate as date) = e.AttDate
for XML path('')
), 1, 2, ''
) as PunchTimes
from (select distinct e.EmployeeId, e.EmployeeCode, e.EmployeeName,
Cast(d.LogDate as date) as AttDate
)
from Employees e join
DeviceLogs d
on e.EmployeeId = d.UserId
where d.LogDate >= '2019-06-01' and
d.LogDate < '2019-06-02'
) e;
注:
请勿在FROM子句中使用逗号。始终使用正确、明确、标准的联接语法。
使用标准日期格式,即“YYYYMMDD”或“YYYY-MM-DD”。
当一个表引用多个表时,限定所有列引用。
指定VARCHAR和类似类型时始终使用长度。默认值因上下文而异,可能会导致难以调试的错误。
只有当您真正理解NOLOCK的功能时,才能使用它。我猜你没有完全理解它。
使用GROUP BY子句而不使用任何聚合函数是个问题。错误很明显,但查询肯定不是。SELECT子句中似乎有一个子查询,筛选使用本地化的日期文本,这保证了转换问题。顺便说一下,NOLOCK表示读取脏数据,是否锁定,同时使用过多的锁定。看起来您遇到了性能问题,并试图用NOLOCK来掩盖它。这实际上会让事情变得更糟。至于错误,它是由子查询引起的。因为它只是一个子查询,而不是实际的聚合函数,所以它不能包含GROUP BY子句或聚合函数中没有的任何列。在SQL Server 2017中,您可以使用STRING_AGG进行此操作。在早期版本中,您必须使用SQLCLR方法进行字符串聚合没有SQL Server 2015版本-我们有2012年、2014年、2016年、2017年和2019年的版本-请选择已经存在的版本。我怀疑这个错误是关于子查询的,而不是外部查询。不,Castd.LogDate是日期,但castdl.LogDate不是日期。很容易错过,但它们都是GROUP BY中所必需的,或者对castdl.LogDate as date的引用更改为d.LogDate。将castdl.LogDate as date添加到GROUP BY子句中是不可能的,因为dl只出现在子查询中,它正试图执行字符串聚合,与SQL Server 2017的string_AGG或MySQL的GROUP_CONCAT一样。这在以前的版本中无法工作。Gordon Linoff通过完全删除GROUP by来展示这是如何工作的。毕竟,它只用于为字符串聚合提供不同的键。如果查询包含其他聚合,比如SUM,就不可能使用DISTINCTApologies,你是对的,我误读了子查询中的引用。实际的解决方案不需要重写,但另一个问题是在子查询中使用dl.LogDate而不是d.LogDate。PunchTimes=StuffSelect','+convertvarchar,dl.LogDate,8来自DeviceLogs dl和NoLock,其中dl.UserId=e.EmployeeId和castdl.LogDate as date=castd.LogDate as date作为XML路径的日期,1,2,GROUP BY中没有聚合函数。cast不是聚合函数