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


68

我试图对别名列(以下示例)执行操作分组,但无法确定正确的语法。

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

正确的语法是什么?


编辑

进一步扩展问题(我没想到我会收到答案),解决方案是否仍适用于CASE别名列?

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

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

Answers:


80

您传递要分组的表达式而不是别名

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

无需将“,”放在GROUP BY中。可以使用或不使用','来指示分组,您甚至可以避免输入错误(例如','),因此不会出现无效的查询错误
Michael Buen

5
您应该将其保留,至少要区分“ x,yz”和“ xy,z”,后者将汇总到同一字符串而无需逗号。
ConcernedOfTunbridgeWells,2009年

2
@NXC:“ GROUP BY LastName + FirstName”可能会落入您解释的陷阱,但是您不能按此分组,并且在SELECT中具有“ LastName +','+ FirstName”。但是,使用“ GROUP BY LastName,FirstName”可以。(请参阅我对发布者问题的评论。)
MatBailie,2009年

1
+1 Dems GROUP BY Lastname,Firstname就可以了。此处的说明ienablemuch.com/2010/04/some-wrong-voted-answer-on.html
Michael Buen 2010年

4
@ConcernedOfTunbridgeWells六年后,我现在才意识到我删除“,”的建议的困惑来自何处,当我说“只是逐条删除”,时,我的意思是从GROUP BY,然后按照事物的实体(即姓氏和名字)对事物进行分组,而不是从SELECT中删除串联;实际上,我在第二句话中提到了我想要实现的目标。
Michael Buen 2015年

44

这就是我的工作。

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

9

不幸的是,您不能在GROUP BY语句中引用您的别名,您将不得不再次编写逻辑,这看起来很令人惊奇。

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

或者,您可以将选择放入子选择或公共表表达式中,然后可以对列名称进行分组(不再是别名)。


6

抱歉,这对于MS SQL Server是不可能的(尽管对于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 ', '

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

以下查询速度较慢(它先尝试计算选择表达式,然后根据该计算对记录进行分组)。

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

FWIW您还可以在MySQL的GROUP BY中使用列别名。但是严格来说,SQL标准不支持它。
比尔·卡温

3

给定您已编辑的问题描述,我建议使用COALESCE()而不是笨拙的CASE表达方式:

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

3

我的猜测是:

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

Oracle有类似的限制,这很烦人。我很好奇是否存在更好的解决方案。

为了回答问题的后半部分,此限制也适用于更复杂的表达式,例如case语句。我看到的最好的建议是使用子选择来命名复杂表达式。


1
无需将“,”放在GROUP BY中。可以使用或不使用','来指示分组,您甚至可以避免输入错误(例如','),因此不会出现无效的查询错误
Michael Buen

真正。但是我发现上面的内容更加清晰。显然,您的子选择解决方案更加清晰。;-)
乔恩·埃里克森

您需要用逗号来避免'ab,c'与'a,bc'的大小写。他们将不加逗号地汇总。
Eric J.

@EricJ。我的第一句话是要从GROUP BY中完全删除连接,而不是建议仅删除字符串',',然后保留连接。即使完全删除GROUP BY上的串联,也没有极端情况。我对您的答案的第一个评论(仅删除字符串“,”)令人困惑,似乎我建议将串联保留在GROUP BY上,而仅删除字符串“,”,但这不是我的意思,对不起那混乱。GROUP BY串联的效果较慢:ienablemuch.com/2010/04/some-wrong-voted-answer-on.html
Michael Buen

答案与已接受的答案相同,但此答案很有用。也许在您的答案中添加它,使您的答案与已接受的答案有所不同?当我们被迫处理遗留物时,可以帮助像我这样的人。
Tschallacka

3

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

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

1
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语句)永远无法为两个不同的输入给出相同的答案。

如果您使用以下方法,则不是这种情况:

LEFT(FirstName, 1) + ' ' + LastName

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

如果您希望输出两次有“ J Taylor”(每个人一个):

GROUP BY LastName, FirstName

但是,如果只需要一行“ J Taylor”,则需要:

GROUP BY LastName, LEFT(FirstName, 1)

0

如果要避免在查询中两次出现case语句的混乱情况,则可能需要将其放在User-Defined-Function中。

抱歉,SQL Server无法在Group By子句之前呈现数据集,因此列别名不可用。您可以在订购依据中使用它。


0

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

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

我真的很喜欢这种语法。为什么不在其他任何地方实施呢?这是一个不错的捷径,但我认为它会引起其他问题?


3
这仍然是可能的,但通常对此并不满意。开发人员最终将新列添加到列列表的中间,然后意外更改了分组条件。这是可行的方法之一,但被认为是不良形式,例如在查询中放入select * from。
Shane Delmore,

@ShaneDelmore我知道这是一个古老的线程,但是今天哪些引擎支持此语法?这个用词是什么?您可以在其他条款(例如WHERE/ HAVING)中使用此类非别名吗?如果是这样,引擎如何知道如何将字段#2与整数2(例如WHERE 2 is not NULL/ HAVING 2 = 1)区分开来
-mpag


0

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

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

(即,SQL Server抱怨您未在“分组依据”或聚合函数中包含“金额”字段)

...记住要在SELECT中放置完全相同的功能...

SELECT AccountNumber, ISNULL(Amount, 0) AS MyAlias
FROM Transactions
GROUP BY AccountNumber, ISNULL(Amount, 0)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.