如何在MS-SQL Server中的别名列上执行GROUP BY?

我试图通过对别名列(下面的示例) 操作执行一个组,但无法确定正确的语法。

SELECT LastName + ', ' + FirstName AS 'FullName' FROM customers GROUP BY 'FullName' 

什么是正确的语法?


编辑

进一步扩展问题(我没有预料到我收到的答案)该解决scheme是否仍然适用于CASEED别名列?

 SELECT CASE WHEN LastName IS NULL THEN FirstName WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName END AS 'FullName' FROM customers GROUP BY LastName, FirstName 

答案是肯定的,它仍然适用。

你传递你想要分组的expression式,而不是别名

 SELECT LastName + ', ' + FirstName AS 'FullName' FROM customers GROUP BY LastName + ', ' + FirstName 

这就是我所做的。

 SELECT FullName FROM ( SELECT LastName + ', ' + FirstName AS FullName FROM customers ) as sub GROUP BY FullName 

这种技术直接应用于“编辑”场景:

 SELECT FullName FROM ( SELECT CASE WHEN LastName IS NULL THEN FirstName WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName END AS FullName FROM customers ) as sub GROUP BY FullName 

不幸的是,你不能在GROUP BY语句中引用你的别名,你必须重新编写逻辑,看起来好极了。

 SELECT LastName + ', ' + FirstName AS 'FullName' FROM customers GROUP BY LastName + ', ' + FirstName 

或者,您可以将select放入子select表或公用表expression式中,之后您可以对列名进行分组(不再是别名)。

对不起,这是不可能的MS SQL服务器(尽pipe与PostgreSQL可能):

 select lastname + ', ' + firstname as fullname from person group by fullname 

否则就使用这个:

 select x.fullname from ( select lastname + ', ' + firstname as fullname from person ) as x group by x.fullname 

或这个:

 select lastname + ', ' + firstname as fullname from person group by lastname, firstname -- no need to put the ', ' 

上面的查询更快,首先将字段分组,然后计算这些字段。

以下查询较慢(它试图首先计算selectexpression式,然后根据该计算对logging进行分组)。

 select lastname + ', ' + firstname as fullname from person group by lastname + ', ' + firstname 

鉴于你编辑的问题描述,我build议使用COALESCE()而不是那个笨拙的CASEexpression式:

 SELECT FullName FROM ( SELECT COALESCE(LastName+', '+FirstName, FirstName) AS FullName FROM customers ) c GROUP BY FullName; 

我的猜测是:

 SELECT LastName + ', ' + FirstName AS 'FullName' FROM customers GROUP BY LastName + ', ' + FirstName 

Oracle有一个类似的限制,这是令人讨厌的。 我很好奇,如果有更好的解决scheme。

为了回答问题的后半部分,这个限制适用于更复杂的expression式,比如你的case语句。 我见过的最好的build议是使用子select来命名复杂的expression式。

 SELECT CASE WHEN LastName IS NULL THEN FirstName WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName END AS 'FullName' FROM customers GROUP BY LastName, FirstName 

这是有效的,因为你使用的公式(CASE语句)决不能给两个不同的input提供相同的答案。

如果您使用了类似的情况,则不是这种情况:

 LEFT(FirstName, 1) + ' ' + LastName 

在这种情况下,“詹姆斯·泰勒”和“约翰·泰勒”都会导致“J泰勒”。

如果你想让你的输出有两次“J泰勒”(每个人一个):

 GROUP BY LastName, FirstName 

但是,如果你只想要一行“J泰勒”,你会想要:

 GROUP BY LastName, LEFT(FirstName, 1) 

如果要避免查询中的case语句混乱两次,则可能需要将其置于用户定义的函数中。

对不起,但SQL Server不会在Group By子句之前呈现数据集,所以列别名不可用。 你可以在Order By中使用它。

在旧的FoxPro中 (我从2.5版本开始就没有使用过),你可以这样写:

 SELECT LastName + ', ' + FirstName AS 'FullName', Birthday, Title FROM customers GROUP BY 1,3,2 

我真的很喜欢这个语法。 为什么不在其他地方实施? 这是一个很好的捷径,但我认为它会导致其他问题?

 SELECT CASE WHEN LastName IS NULL THEN FirstName WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName END AS 'FullName' FROM customers GROUP BY 1` 

对于任何发现自己有以下问题的人(通过确保零和空值被视为等于)进行分组…

 SELECT AccountNumber, Amount AS MyAlias FROM Transactions GROUP BY AccountNumber, ISNULL(Amount, 0) 

(即SQL Server的抱怨,你没有包括在您的分组依据或聚合函数字段金额)

…记得把你的SELECT中完全相同的function…

 SELECT AccountNumber, ISNULL(Amount, 0) AS MyAlias FROM Transactions GROUP BY AccountNumber, ISNULL(Amount, 0) 

您可以使用CROSS APPLY来创build一个别名,并在GROUP BY子句中使用它,如下所示:

 SELECT FullName FROM Customers CROSS APPLY (SELECT LastName + ', ' + FirstName AS FullName) Alias GROUP BY FullName