首页 > 解决方案 > T-SQL GROUP BY 也使用 JOIN、聚合和外部引用错误

问题描述

我正在学习 SQL 并尝试加入几个模拟酒店表并进行一个简单的查询,以显示客人的串联姓名和他们所做的预订数量。

无论我如何尝试重组我的查询,我都会遇到两个错误之一。

如果我尝试这种方式:

SELECT 
    [Guests].FirstName + ' ' + [Guests].LastName AS 'Guest Name', 
    [ReservationsRooms].Reservation_ID
FROM 
    [ReservationsRooms]
JOIN 
    [Reservations] ON [ReservationsRooms].Reservation_ID = [Reservations].Reservation_ID
JOIN 
    [Guests] ON [Reservations].Guest_ID = [Guests].Guest_ID
GROUP BY 
    [Guests].Guest_ID

我收到一个错误:

列“Guests.FirstName”在选择列表中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

我认为这可能是一个模棱两可的问题,所以我也尝试如下:

SELECT 
    [Guests].FirstName + ' ' + [Guests].LastName AS 'Guest Name', 
    COUNT([ReservationsRooms].Reservation_ID) AS 'Reservations'
FROM 
    [ReservationsRooms]
JOIN 
    [Reservations] ON [ReservationsRooms].Reservation_ID = [Reservations].Reservation_ID
JOIN 
    [Guests] ON [Reservations].Guest_ID = [Guests].Guest_ID
GROUP BY 
    [Guests].Guest_ID, 'Guest Name'

但这也导致了一个错误:

每个 GROUP BY 表达式必须至少包含一个不是外部引用的列。

我正在尝试创建一个返回如下内容的查询结果:

Reservations    Guest Name
-------------------------------
4               Mack Simmer
3               Bettyann Seery
2               Duane Cullison
2               Aurore Lipton
2               Maritza Tilton
2               Joleen Tison

具体来说,我只想要查询中的这两列,但似乎找不到这样做的方法。

标签: sql-servertsqlgroup-by

解决方案


这就是为什么我真的不喜欢人们使用文字字符串作为别名的原因;这个工作的唯一地方是在SELECT. GROUP BY 'Guest Name'并不意味着“按别名为'Guest Name'”的列分组,它的意思是“按文字字符串 'Guest Name'分组”,不出所料,这没有任何意义。

即使您为别名使用了更好的定界标识符,无论是 T-SQL 的括号 ( []) 还是 ANSI-SQL 的双引号 ( "),您仍然无法执行您所做的操作,因为您无法通过它是中的别名GROUP BY(例如GROUP BY [Guest Name]会产生错误"Invalid column name 'Guest Name'")。这是由于SELECT 语句的逻辑处理顺序,并且GROUP BY在(分别为步骤 5 和 8)之前处理了几个步骤SELECT,因此别名在GROUP BY.

相反,您要么需要GROUP BY表达式本身,要么需要表达式中包含的列。我个人会在这里使用后者。

SELECT G.FirstName + ' ' + G.LastName AS GuestName, --Generally, avoid names that need delimit identification
       COUNT(RR.Reservation_ID) AS Reservations
FROM dbo.ReservationsRooms RR --Always schema qualify. Also aliases are good.
     JOIN dbo.Reservations ON RR.Reservation_ID = R.Reservation_ID
     JOIN dbo.Guests G ON R.Guest_ID = G.Guest_ID
GROUP BY G.FirstName,
         G.LastName,
         G.Guest_ID;

或者,您可以完全省略G.FirstNameandG.LastName并将GROUP BY表达式 for 包装GuestName在 a 内MAX

MAX(G.FirstName + ' ' + G.LastName AS GuestName) AS GuestName

推荐阅读