Reputation: 5247
I'm writing a query that needs to find distinct city/state/country locations in a postal code database that match a city name. The columns are:
Country, PostalCode, City, State, StateAbbr, County, CountryCode, Latitude, Longitude
The result set needs to include all these columns.
Using the query string: "Brooklyn" as an example, I am able to at least assign a rank to each row like this:
select b.*,
(select count(*) from PostalCodes b2
where b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country) as Rank
from PostalCodes b
where b.City LIKE 'Brooklyn%'
The result set has 66 rows, 14 of them are locations with a single entry in the database, so their rank is 1. The remaining 52 rows are for Brooklyn, NY, which has 52 entries in the database, and is assigned a rank of 52.
How do I get distinct rows based on the Rank, and get all the columns in the DB? I don't care which postal code is returned... I just want a single entry per city/state/country.
I'm using SQL Server 2008.
Upvotes: 0
Views: 2763
Reputation: 680
Here's another shot. Note that TOP 1 works because you stated you didn't care which specific row was returned first, and this will return an arbitrary row in cases where Rank > 1.
SELECT X.Rank, Y.*
FROM ( SELECT B.City, B.State, B.Country, COUNT(*) AS [Rank]
FROM PostalCodes B
GROUP BY B.City, B.State, B.Country
) X
JOIN (SELECT ROW_NUMBER() OVER(PARTITION BY City, State, Country ORDER BY City, State, Country) AS RN,
*
FROM Postalcodes)
Y
ON X.City = Y.City
AND X.State = Y.State
AND X.Country = Y.Country
WHERE Y.RN = 1
Here's another attempt.
Note that query performance is going to be heavily dependent on the indexes available. I believe I have worked with this table before, and as provided by the vendor the indexes are not optimal for this sort of query.
SELECT RNK.Rank, PC.*
FROM Postalcodes PC
JOIN (
SELECT MAX(PostalCode) as PostalCode,
City,
StateAbbr,
CountryCode,
Count(*) AS Rank
FROM Postalcodes P
group by city, stateabbr, countrycode
) RNK
ON RNK.PostalCode = PC.PostalCode
AND RNK.City = PC.City
AND RNK.StateAbbr = PC.StateAbbr
AND RNK.CountryCode = PC.CountryCode
Upvotes: 1
Reputation: 680
From your query, you are looking for a count of postal codes by City, State, and Country.
I think this will give you what you are looking for:
SELECT B.City, B.State, B.Country, COUNT(*) AS Rank
FROM PostalCodes B
GROUP BY B.City, B.State, B.Country
Upvotes: 0
Reputation: 1066
Assuming each record with the same city/state/country combination has the same value in every other field, you can use this query (although it is a bit of a hack):
SELECT b.*,
PostalCode = (SELECT TOP 1 PostalCode FROM PostalCodes b2 WHERE b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country),
StateAbbr = (SELECT TOP 1 StateAbbr FROM PostalCodes b2 WHERE b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country),
County = (SELECT TOP 1 County FROM PostalCodes b2 WHERE b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country),
CountryCode = (SELECT TOP 1 CountryCode FROM PostalCodes b2 WHERE b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country),
Latitude = (SELECT TOP 1 Latitude FROM PostalCodes b2 WHERE b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country),
Longitude = (SELECT TOP 1 Longitude FROM PostalCodes b2 WHERE b.City = b2.City AND b.[State] = b2.[State] AND b.Country = b2.Country)
FROM(
SELECT DISTINCT CITY, STATE, COUNTRY
FROM PostalCodes
) b
The problem with your request is typically when you group by a set of fields (in your case city/state/country) you don't include any other columns. This is a way around that, although it is pretty slow and could be optimized.
Upvotes: 1
Reputation: 570
select COUNT(City),City,State,Country
from
PostalCodes
group by City,State,Country
order by COUNT(City)
Upvotes: 0