首页 > 解决方案 > 在 SQL 中使用 Group By 和 Aggregate - 获取错误“选择列表中的列无效,因为它不包含在聚合函数或 GROUP BY 中”

问题描述

我正在加入来自 2 个表的数据,以获取数据库中客户的最后交易日期。这是我正在尝试做的一个简化示例:

SELECT c.CustomerID
       c.CustomerFirstName
       c.CustomerLastName
   MAX(t.TransactionDate)

FROM [db].[customertable] C

LEFT JOIN [TransactionTable] T on c.CustomerID = t.CustomerID

GROUP BY c.CustomerID

ORDER BY t.TransactionDate

但是,在执行此代码时,我收到此错误消息:

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

我花了一些时间尝试解决这个问题,发现将 MAX() 放在客户的名字和姓氏前面是可行的,消除了错误消息,输出似乎是我想要的。

虽然我想知道这是否是不好的做法?我按 CustomerID 进行分组,这是一个唯一的参考 - 每个 CustomerID 只有一个名字和一个姓氏,所以我是否正确地说将最大值放在名字/姓氏前面不会有任何除了使我的查询工作之外的影响?

我在网上找到的其他解决方案建议子查询,但我仍在学习 SQL,所以不知道该怎么做。

谢谢

标签: sqlsql-servertsqlaggregate-functions

解决方案


只需包括所有非聚合列:

SELECT c.CustomerID, c.CustomerFirstName, c.CustomerLastName,
       MAX(t.TransactionDate)
FROM [db].[customertable] C LEFT JOIN
     [TransactionTable] T
     ON c.CustomerID = t.CustomerID
GROUP BY c.CustomerID, c.CustomerFirstName, c.CustomerLastName;

通常,使用相关子查询或横向连接(即)这种类型的查询会更快apply

select c.*,  -- or whatever columns you want
       t.max_TransactionDate
from [db].[customertable] C outer apply
     (select max(t.TransactionDate) as max_TransactionDate
      from [TransactionTable] t
      where c.CustomerID = t.CustomerID
     ) t;

特别是,如果有一个索引TransactionTable(CustomerID, TransactionDate desc),这应该比带有group by.


推荐阅读