How to select multiple columns but only group by one?

  • I have a problem with group by, I want to select multiple columns but group by only one column. The query below is what I tried, but it gave me an error.

    SELECT Rls.RoleName,Pro.[FirstName],Pro.[LastName],Count(UR.[RoleId]) as [Count]
    from [b.website-sitecore-core].[dbo].[aspnet_UsersInRoles] UR
    inner join [b.website-professional-au].[dbo].[Profile]  Pro
    on UR.UserId = Pro.Id
    inner join [b.website-sitecore-core].[dbo].[aspnet_Roles] Rls
    on Rls.RoleId = UR.RoleId
    inner join [b.website-professional-au].[dbo].[Gender] Gn
    on gn.Id = pro.GenderId
    GROUP BY Rls.RoleName;
    
  • In SQL Server you can only select columns that are part of the GROUP BY clause, or aggregate functions on any of the other columns. I've blogged about this in detail here. So you have two options:

    1. Add the additional columns to the GROUP BY clause:

      GROUP BY Rls.RoleName, Pro.[FirstName], Pro.[LastName]
      
    2. Add some aggregate function on the relevant columns:

      SELECT Rls.RoleName, MAX(Pro.[FirstName]), MAX(Pro.[LastName])
      

    The second solution is mostly a workaround and an indication that you should fix something more general with your query.

    *"In SQL Server you can only select columns that are part of the GROUP BY clause, or aggregate functions on any of the other columns..."* is something what I was looking for.. Thnx

    NOTE: these two options can provide absolutely WRONG results! `GROUP BY A,B,C` can be totally different than what you want to get in comparison with `GROUP BY A`. and also, usually we can't use some aggregate function to get related column value. check this answer as a solution

    I know that the two queries will give exactly same results in my case (always). But I want to know which is more efficient. Lets say Rolename is pk in one of the table being joined (so indexed) and the other columns are type varchar. basically what does max do here ?

    @MohitSingh: I recommend asking a new question

  • Note: This answer is intended as a supplement to @Lukas Eder's answer

    If there are multiple values present for the fields SELECTed but a field you wish to GROUP BY, you could instead grab the top matching line, rather than waiting for an aggregation (MAX) to return.

    SELECT i.RoleName, i.*
    FROM Rls JOIN 
    (SELECT TOP 1 R.Rolename, Pro.FirstName, Pro.LastName FROM Rls as R JOIN Pro ON ... ) as i
         ON i.Rolename=Rls.RoleName
    

    if you want ALL values to return in those other columns, but want to collapse it to a single entry see: https://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM