Reputation: 121
I have a table I am trying to clean up so I just need the first address in the table for each ClientId
Table Addresses
has these columns
Pk[Id]
[ClientId]
[AddressLine1]
[AddressLine2]
Query I use:
SELECT *
FROM Addresses
ORDER BY ClientId
result =
1 1 foo bar
2 1 foo2 bar2
3 1 foo3 bar3
4 1 foo4 bar4
5 2 foo bar2
95 2 foo bar5
97 2 foo bar6
8 3 foo2 bar7
wanted result =
1 1 foo bar <--is first match for clientid = 1
5 2 foo bar2 <-- is first match for clientid = 2
8 3 foo2 bar7 <-- is first match for clientid = 3
This need to work for n clientids
I tried
SELECT *
FROM Addresses
GROUP BY ClientId
The resulting error is (Column 'Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.)
What am I missing here?
Upvotes: 0
Views: 993
Reputation: 247680
SQL Server requires that when using a GROUP BY you need to either use an aggregate function on the columns in the select list or add them to the GROUP BY.
Your original query could be changed to use the following:
select a.id, a.clientid, a.address1, a.address2
from addresses a
inner join
(
select clientid, MIN(id) id
from addresses
group by clientid
) d
on a.clientid = d.clientid
and a.id = d.id;
As you can see this uses a subquery that returns the min(id)
for each clientId
, this only groups by the clientid
. You then join this to your table to return only those rows with the min id for each client.
Upvotes: 2
Reputation: 4268
As per the Single-Value Rule: all columns in the select-list must be explicitly part of the GROUP BY criteria, or else inside an aggregate function, e.g. COUNT(), MAX(), etc.
Upvotes: 0
Reputation: 4591
You did SELECT *. Every field in the select list must either be in the GROUP BY clause or inside an agregation function (MAX, MIN, SUM, AVG, etc.).
This explains the error. For the SQL that solves your problem see Goat_CO answer.
Upvotes: 1
Reputation: 34774
You are getting multiple lines because you're selecting a field you don't want to be grouping by. If you just want the first entry for each clientID you can use an analytic function like ROW_NUMBER Try:
SELECT *
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY clientid ORDER BY ID) as RowRank
FROM Addresses)sub
WHERE RowRank = 1
Upvotes: 2