tags:

views:

41

answers:

3

Why this insert is not getting compiled :-

INSERT  INTO dbo.UserGroupsToUsers
                        ( UserID ,
                          LastUpdated ,
                          ID ,
                          UserGroupID 
                        )
                        SELECT  @MergeToUserID ,
                                GETDATE() ,
                                MAX(ID) + 1 ,
                                UserGroupID
                        FROM    dbo.UserGroupsToUsers
                        WHERE   UserID = @MergeFromUserID

Error: Column 'dbo.UserGroupsToUsers.UserGroupID' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.

+3  A: 

You should make your ID field into an IDENTITY (autoincrementing field) and omit it from the query.

If you can't change the database you could try this:

INSERT  INTO dbo.UserGroupsToUsers
                ( UserID ,
                  LastUpdated ,
                  ID ,
                  UserGroupID 
                )
                SELECT  @MergeToUserID ,
                        GETDATE() ,
                        (SELECT MAX(ID) + 1 FROM dbo.UserGroupsToUsers),
                        UserGroupID
                FROM    dbo.UserGroupsToUsers
                WHERE   UserID = @MergeFromUserID

Important note: This assumes that only one row will be returned. The insert will fail by design if your subquery returns more than one row and ID is a primary key or has a unique constraint.

Mark Byers
Yes, that's a specific answer to how to make this query right.
Alexander
The database is already designed like that...its not in my hands..anyways the issue is not with IDENTITY, the error is something else..i am not able to understand..i have run these kind of queries earlier..
Puneet Dudeja
Check my updated comment in this case.
Alexander
@Alexander: OK I'll leave my answer as it was and vote up yours instead. I don't like giving hacks anyway. :)
Mark Byers
I added the hack back with a note about how it behaves, though I think the IDENTITY solution is the better way.
Mark Byers
+3  A: 

MAX(ID) is an aggregate function. Like all aggregate functions, it requires grouping on the rest of the fields. After WHERE clause, add a group by clause on all the rest of the fields (aliases).

This is general, but for this case use Mark Byers solution.

Another idea is to not do MAX(), but rather like this:

INSERT  INTO dbo.UserGroupsToUsers
                        ( UserID ,
                          LastUpdated ,
                          ID ,
                          UserGroupID 
                        )
                        SELECT TOP 1 @MergeToUserID ,
                                GETDATE() ,
                                ID +1,
                                (SELECT UserGroupID FROM dbo.UserGroupsToUsers WHERE   UserID = @MergeFromUserID)
                        FROM    dbo.UserGroupsToUsers
                        ORDER BY ID DESC
Alexander
This will not return ID value as (Max+1), a previous solution posted was using subquery for ID as (Select max(ID)+1 from table) and that was right. I wanted to accept that solution but now it is not here.
Puneet Dudeja
It will. Order it by the ID descending, take the top 1, that's MAX. Then add 1. That's what I wrote.And like I mentioned, get UserGroupID value in a separate query. It doesn't matter which way you go, it just has to be another query for one of these tasks.
Alexander
Hmm actually this doesn't work I think because of the WHERE clause...
Mark Byers
I don't understand how it will be (Max+1). Because, first the records will be selected based on "where" condition from UserGroupsToUsers which is "UserID = @MergeFromUserID", and then the selected records will be ordered by ID DESC. (And we don't know whether the ID for @MergeFromUserID is maximum in the table or not).
Puneet Dudeja
Like I said, omit the Where clause, because even with MAX you would get the same result. The where clause is the problem.There. I've edited the answer, erased the where clause and the comment telling to erase it, and added a separate select clause for UserGroupID, like the comment specified.
Alexander
A: 

You use a MAX(ID), this means the query uses grouping. But you do not use a aggregate function on UserGroupID, so SQL does not know what value to pick from the (possible) values.

Probably there is only one value, and you know that, but the SQL compiler does not know that.

Better to wrap UserGroupID also in a MAX, MIN, or other aggregate function.

GvS