views:

933

answers:

10

I'm trying to perform a group by action on an aliased column (example below) but can't determine the proper syntax.

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

What is the correct syntax?


EDIT

Extending the question further (I had not expected the answers I had received) would the solution still apply for a CASEed aliased column?

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

And the answer is yes it does still apply.

+12  A: 

You pass the expression you want to group by rather than the alias

SELECT       LastName + ', ' + FirstName AS 'FullName'
FROM         customers
GROUP BY      LastName + ', ' + FirstName
cmsjr
no need to put the ', ' in GROUP BY. the grouping can be indicated with or without the ', ', you can even avoid the typo (e.g. ','), so no invalid query error could arise
Michael Buen
Are you referring to my suggestion, or to removing the + ', ' + from the group by expression?
cmsjr
just remove the ', ' in group by clause. this works: select lastname + ', ' + firstname as fullnamefrom persongroup by lastname, firstname
Michael Buen
You should leave it in, at least to differentiate between 'x, yz' and 'xy, z' which would roll up to the same string without the comma.
ConcernedOfTunbridgeWells
@NXC: "GROUP BY LastName + FirstName" can fall into the trap you explain, but you can't group by that and have "LastName + ', ' + FirstName" in the SELECT. Using "GROUP BY LastName, FirstName", however, would be fine. (See my comment on the poster's question.)
Dems
+1  A: 

Unfortunately you can't reference your alias in the GROUP BY statement, you'll have to write the logic again, amazing as that seems.

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

Alternately you could put the select into a subselect or common table expression, after which you could group on the column name (no longer an alias.)

Barry Fandango
no need to put the ', ' in GROUP BY. the grouping can be indicated with or without the ', ', you can even avoid the typo (e.g. ','), so no invalid query error could arise
Michael Buen
+1  A: 

My guess is:

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

Oracle has a similar limitation, which is annoying. I'm curious if there exists a better solution.

To answer the second half of the question, this limitation applies to more complex expressions such as your case statement as well. The best suggestion I've seen it to use a sub-select to name the complex expression.

Jon Ericson
no need to put the ', ' in GROUP BY. the grouping can be indicated with or without the ', ', you can even avoid the typo (e.g. ','), so no invalid query error could arise
Michael Buen
True. But I find the above a touch more clear. Your sub-select solution is even clearer, obviously. ;-)
Jon Ericson
A: 

Good time to use DISTINCT:

SELECT  DISTINCT    LastName + ', ' + FirstName AS 'FullName'
FROM         customers

For the new edit, this would be the best alternative:

SELECT FullName FROM
(SELECT       
    CASE
        WHEN LastName IS NULL THEN FirstName
        WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
    END AS 'FullName'
FROM         customers) A
GROUP BY     'FullName'
Otávio Décio
Of course, that won't work if you mean GROUP BY. ;-) (For instance, if you want to count the number of customers who have each fist and last name.)
Jon Ericson
I'm just giving the simplest solution that addresses the question... :)
Otávio Décio
Sorry, but's that's not the simplest answer...
Dems
+5  A: 

This is what I do.

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


This technique applies in a straightforward way to your "edit" scenario:

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
David B
+1  A: 

Sorry, this is not possible with MS SQL Server (possible though with PostgreSQL):

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

Otherwise just use this:

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

Or this:

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

The above query is faster, groups the fields first, then compute those fields.

The following query is slower (it tries to compute first the select expression, then it groups the records based on that computation).

select lastname + ', ' + firstname as fullname
from person
group by lastname + ', ' + firstname
Michael Buen
FWIW you can also use column aliases in GROUP BY in MySQL. But strictly, it isn't supported by the SQL standard.
Bill Karwin
A: 

In the old FoxPro (I haven't used it since version 2.5), you could write something like this:

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

I really liked that syntax. Why isn't it implemented anywhere else? It's a nice shortcut, but I assume it causes other problems?

EJB
This is still possible but is generally frowned upon. Developers end up adding a new column to the middle of your column list and then unexpectedly changing the grouping criteria. It's one of those things that works but is considered poor form, like putting select * from in your queries.
ShaneD
Boy, how is it that I never noticed you could still do that...for some reason I thought it was invalid, but just tried - it works. I'll use for some adhoc stuff, but not in my code...thanks.
EJB
+1  A: 

Given your edited problem description, I'd suggest using COALESCE() instead of that unwieldy CASE expression:

SELECT FullName
FROM (
  SELECT COALESCE(LastName+', '+FirstName, FirstName) AS FullName
  FROM customers
) c
GROUP BY FullName;
Bill Karwin
A: 
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

This works because the formula you use (the CASE statement) can never give the same answer for two different inputs.

This is not the case if you used something like:

LEFT(FirstName, 1) + ' ' + LastName

In such a case "James Taylor" and "John Taylor" would both result in "J Taylor".

If you wanted your output to have "J Taylor" twice (one for each person):

GROUP BY LastName, FirstName

If, however, you wanted just one row of "J Taylor" you'd want:

GROUP BY LastName, LEFT(FirstName, 1)
Dems
A: 

If you want to avoid the mess of the case statement being in your query twice, you may want to place it in a User-Defined-Function.

Sorry, but SQL Server would not render the dataset before the Group By clause so the column alias is not available. You could use it in the Order By.

Jeff O