Counting occurrences of distinct multiple columns in SQL - sql

I'm trying to count the occurrences of a distinct set of cities and countries in a user table.
The table is set out similar to:
userid city country
------ --------- --------------
1 Cambridge United Kingdom
2 London United Kingdom
3 Cambridge United Kingdom
4 New York United States
What I need is a list of every city, country pair with the number of occurrences:
Cambridge, United Kingdom, 2
London, United Kingdom, 1
New York, United States, 1
Currently I run an SQL query to get the distinct pairs:
$array = SELECT DISTINCT city, country FROM usertable
then read it into an array in PHP, and loop through the array, running a query to count each occurrences for each row in the array:
SELECT count(*) FROM usertable
WHERE city = $array['city']
AND country = $array['country']
I'm assuming my scant grasp of SQL is missing something - what would be the correct way to do this, preferably without the intervention of PHP?

select city, country, count(*)
from usertable
group by city, country

What you need is a group by:
Select city, country, count(*) as counter
from usertable
group by city, country

SELECT cityandcountry, count(*) as occurrences FROM (
SELECT DISTINCT concat(city, country) FROM tablename
) as baseview;
if you want city and country preformated, or
SELECT cityandcountry, count(*) as occurrences FROM (
SELECT DISTINCT city, country FROM tablename
) as baseview;
if not.

Related

SQL query tutorial

given that there are 2 such entities
city(name, country, population)
country(code, name, capital, population)
and the question is that there exist cities in different countries that have the same name. For instance, paris in texas, usa, and paris in france. we assume, however, that every city in one country has a unique name in that country. find the names of cities that have a unique name.
would this work then
SELECT DISTINCT c1.name
FROM city c1, city c2
WHERE c1.name<>c2.name;
This will find all the cities that are unique in the database.
SELECT name
FROM city
Group by city
Having count(city) = 1

Get maximum number with combination of columns

I have table with columns like AutoID, Number, Name, City, State, Country.
What I wanted is the maximum number entered in the "Number" column with the combination of Name, City, State and Country.
Example:
Name City State Country
Smith NY NY USA
John NY NY USA
John NJ NY USA
Now smith should get "Number" 1, John 2, and again John(in NJ) 1 as he is the first from NJ.
I can simply put a where clause in query and get the max number + 1. But the problem is that when I have huge amount of data and the number of users increases, my query will be really slow. I am also inserting data in the same table so it will keep on piling.
I hope I have made my self clear.
Vipul Parekh
I am guessing that this is what you want:
Name City State Country Number
Smith NY NY USA 1
John NY NY USA 2
John NJ NY USA 1
This is provided by row_number():
select name, city,state, country,
row_number() over (partition by city, state, country order by (select null)) as Number
from table t;
Note that the sequencing of the Number within a group is arbitrary, because you don't provide an id or createdat column. There is no guarantee that it is in the same order as the table, because SQL tables are inherently unordered.
You can create a trigger on your table. whenever you insert a row it will count the number of rows and update the latest one with a number with the count + 1.
To get around slowness you can create a index on Name, City, State and Country.
Let me know if you need a sample code or some pointers.
You can Use ROW_NUMBER
SELECT * FROM
(
Select Name,
City,
State,
Country,
Row_Number() over (Partition by City, State, Country ORDER BY Name) AS Number
From table1
) AS T
WORKING FIDDLE
1)
WITH Optimize_CTE (id, cityid,stateid, countryid)
AS
-- Define the CTE query.
(
SELECT id, cityid,stateid, countryid
FROM Optimize
WHERE id IS NOT NULL
)
-- Define the outer query referencing the CTE name.
SELECT id,
convert(Varchar(255),cityid) as CityId,
convert(Varchar(255),stateid) as StateId,
convert(Varchar(255),countryid) as CountryId
FROM Optimize_CTE OPTION (MAXRECURSION 1)
DECLARE #RowsPerPage INT = 10, #PageNumber INT = 1
SELECT InvoiceID, CustomerID
FROM dbo.SalesInvoice
ORDER BY InvoiceID
OFFSET (#PageNumber-1)*#RowsPerPage ROWS
FETCH NEXT #RowsPerPage ROWS ONLY
GO

SQL find repeated values

I need to identify rows where a certain value is repeated. Here is a sample table:
COUNTRY CITY
Italy Milan
Englad London
USA New York
Canada London
USA Atlanta
The query should return...
COUNTRY CITY
Englad London
Canada London
...because London is repeated. Thank you in advance for your help.
The easiest way is to use a subquery that counts the number of times each city appears (and filter to those values that appear more than once):
SELECT * FROM Cities
WHERE City in
(
SELECT City FROM Cities
GROUP BY City
HAVING COUNT(*) > 1
)
If your DBMS supports windowed aggregates.
SELECT COUNTRY,
CITY
FROM (SELECT COUNTRY,
CITY,
COUNT(*) OVER (PARTITION BY CITY) AS Cnt
FROM Cities) T
WHERE Cnt > 1
SQL Fiddle
select country, city
from aTable
where city in
(
select city
from aTable
group by city
HAVING count(1) > 1
)
Try it here: http://sqlfiddle.com/#!3/e9b1a/1
Or if the same city & country combo appears twice and you're only interested where the countries are different:
select distinct country, city
from aTable
where city in
(
select city
from aTable
group by city
HAVING count(distinct country) > 1
)
Try it here: http://sqlfiddle.com/#!3/2dfaa/2
This one works. Got it from my wife (she finally had time to look into this). Thought you might be interested.
SELECT * FROM Cities
WHERE City in ( select city
from (SELECT City,
count(distinct country)
FROM Cities
GROUP BY City
HAVING count(distinct country) > 1) a )

Group By query - any other way?

I have the following table that contains the following data:
http://img513.imageshack.us/img513/9039/mycities.png
The CREATE statement and the inserts are at http://snipt.org/xoKl .
The table is a list of cities and each city belongs to a region and a country and each city has a founding date. The goal here is to get for each "Country / Region" pair a list of the oldest cities. We need the oldest city on the east coast of Canada, the oldest city on the west coast of the U.S and so on ...
The query that I use right now is:
SELECT * FROM MyCities
INNER JOIN
(SELECT Country, Region, MIN(FoundingDate) AS CityFoundingDate
FROM MyCities
GROUP BY Country, Region ) AS subquery
ON subquery.CityFoundingDate = MyCities.FoundingDate
AND MyCities.Country = subquery.Country
AND MyCities.Region = subquery.Region
I just want to know whether there are other ways to write this group by query or not. :-)
Is this query efficient or not?
Looking forward to a discussion.
What about?
select country, region, city from MyCities mc1
where foundingDate <= ALL (
select foundingDate from MyCities as mc2
where mc1.country = mc2.country and mc1.region = mc2.region
)
How about something like this?
Should work in Oracle (although I can't test it right now)
SELECT country, region, city, foundingdate
FROM (
SELECT country, region, city, foundingdate, MIN(founding_date) OVER PARTITION BY (country, region) min_date
FROM mycities) WHERE foundingdate=min_date
But what if there are two cities founded on the same year in the same country/region?

Select count / duplicates

I have a table with all U.S. zip codes. each row contains the city and state name for the zip code. I'm trying to get a list of cities that show up in multiple states. This wouldn't be a problem if there weren't X amount of zip codes in the same city...
So basically, I just want to the city in a state to count as 1 instead of it counting the city/state 7 times because there are 2+ zip codes in that city/state...
I'm not really sure how to do this. I know I need to use count but how do I tell the mysql to only count a given city/state combo as 1?
SELECT City, Count(City) As theCount
FROM (Select City, State From tblCityStateZips Group By City, State) As C
GROUP By City
HAVING COUNT Count(City) > 1
This would return all cities, with count, that were contained in more than one state.
Greenville 39
Greenwood 2
GreenBriar 3
etc.
First group on state and city, then group the result on city:
select City
from (
select State, City
from ZipCode
group by State, City
) x
group by City
having count(*) > 1
Will this do the trick
Select CityName, Count (Distinct State) as StateCount
From CityStateTable
Group by CityName
HAVING Count (Distinct State) > 1
Try using a select distinct
SELECT DISTINCT city, state FROM table GROUP BY city
You probably should have created a separate table for zip codes then to avoid the duplication.
You want to look into the GROUP BY Aggregate.