如何在 SQL Server 中对别名列执行 GROUP BY?

问题描述 投票:0回答:13

我正在尝试对别名列执行 group by 操作(如下所示),但无法确定正确的语法。

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

正确的语法是什么?

进一步扩展问题(我没想到收到的答案)该解决方案是否仍适用于 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

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

sql sql-server t-sql syntax
13个回答
111
投票

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

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

66
投票

这就是我所做的。

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

14
投票

不幸的是,你无法在 GROUP BY 语句中引用你的别名,你必须重新编写逻辑,这看起来很神奇。

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

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


8
投票

抱歉,这对于 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

4
投票

您可以使用

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

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

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
投票
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

在这种情况下,“James Taylor”和“John Taylor”都会生成“J Taylor”。

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

GROUP BY LastName, FirstName

但是,如果您只想要一排“J Taylor”,您会想要:

GROUP BY LastName, LEFT(FirstName, 1)

0
投票

如果您想避免 case 语句在查询中出现两次的混乱,您可能需要将其放置在用户定义函数中。

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


0
投票

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

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

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


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

0
投票

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

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

(即 SQL Server 抱怨您没有在 Group By 或聚合函数中包含字段 Amount)

...记住在 SELECT 中放置完全相同的函数...

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

0
投票

在此处的答案中添加另一个变体,表明这也是 公用表表达式(CTE)的一个很好的用例。

WITH CustomersWithFullNames AS (
  SELECT LastName + ', ' + FirstName AS FullName, *
  FROM customers
)
SELECT FullName
FROM CustomersWithFullNames 
GROUP BY FullName

在性能方面,这与内部子查询的工作方式相同,但是(至少对我来说)以自上而下的方式阅读起来更容易一些

旁注:一些数据库如snowflake允许您在group by子句中引用投影子句中的表达式

© www.soinside.com 2019 - 2024. All rights reserved.