How to make a raw SQL query that selects the city with the highest population associated with an area code (there are duplicate area codes) - sql

I have a table that has the following columns:
areaCode
zipcode
city
state
population
There are multiple rows with the same area codes that are associated with different cities/zip codes.
I need to select the city with the highest population that corresponds to the area code.
EX:
area_codes / zip / city / state / population
858 94111 San Francisco CA 3905
858 94121 San Francisco CA 34786
914 10010 New York NY 22785
914 10012 New York NY 17738
I want to be able to only select the city San Francisco (with area code of 858) that has the population of 34786 and the row New York (with area code of 914) that has the population of 22785, since they have the highest populations. After selecting these ones I need to create a new table and place them in a new table.

Try This:
Create table MaxPopulation as (select area_codes,city,max(population) from table group by area_codes,city);

A general solution uses ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY area_codes ORDER BY population DESC) rn
FROM yourTable
)
SELECT area_codes, zip, city, state, population
FROM cte
WHERE rn = 1;

INSERT INTO cte_new
SELECT
area_codes,
zip,
city,
state,
MAX(population) population
FROM cte
GROUP BY
area_codes,
zip,
city,
state
Generally I would prefer a grouping function than a window function (parition) since it offers a much better performance. I have skipped the table declaration that you would require before this code

Related

How do I select all values which satisfy certain aggregate properties?

Say, I have a table (named "Customers") which consists of:
CustomerName
Country
City
I am trying to list the names of all customers from cities where there are at least two customers.
This is my initial attempt:
SELECT CustomerName, City
FROM Customers
GROUP BY City
HAVING COUNT(City) > 1
This is the result that I got:
CustomerName
City
Person A
New York
Person C
Los Angeles
Here, Person A is a person from NY who appears on the top of the table and similar for Person B. However, what I wanted was the listing of all customers from New York and LA.
When I tried:
SELECT COUNT(CustomerName), City
FROM Customers
GROUP BY City
HAVING COUNT(City) > 1
I had
COUNT(CustomerName)
City
3
New York
5
Los Angeles
This means that the code is working properly, except that my original code only displays a person on top of the table from NY and LA. How do I resolve this issue?
Get cities with more than 1 customer in a subquery, and use that list to select the customers:
SELECT cst.CustomerName
FROM Customers cst
WHERE Cst.City in (
-- All cities where there are at least two customers
SELECT CstGE2.City
FROM Customers CstGE2
GROUP BY CstGE2.City
HAVING count(*) >= 2
)
How about this? I've taken the city out of the select part since you said you just wanted customer names.
SELECT a.CustomerName
FROM Customers a
WHERE (
SELECT COUNT(b.CustomerName)
FROM Customers b
WHERE b.City = a.City
) > 1
ORDER BY a.CustomerName

SQL - apply single value to all rows in table

I have two tables - one called "customer_data" and one called "weighted_average_rate_charged".
Customer_data
First Name
Last Name
City
Daily_Rate
Total_paid
Jim
Carter
Dallas
$100.00
$600.00
James
Franklin
Houston
$150.00
$900.00
Lily
Smith
Dallas
$90.00
$540.00
Frank
Masters
Dallas
$95.00
$680.00
Jennifer
Brown
Houston
$100.00
$590.00
Weighted_Average_Rate_Charged
I have used the following query:
select
City,
sum(Daily_Rate * Total_Paid)/sum(Total_Paid) as WA_Rate
from customer_data
group by
City
To get my weighted average per city. Now, what i want to do is take the max number, which according to the output below is 130.2013:
City
WA_Rate
Houston
$130.2013
Dallas
$95.1648
And essentially create a new table which is the same as customer_data but with an additional column called "Max_WA_daily" which shows $130.2013 for all entries in that table.
Example:
First Name
Last Name
City
Daily_Rate
Total_paid
Max_WA_daily
Jim
Carter
Dallas
$100.00
$600.00
$130.2013
James
Franklin
Houston
$150.00
$900.00
$130.2013
Lily
Smith
Dallas
$90.00
$540.00
$130.2013
Frank
Masters
Dallas
$95.00
$680.00
$130.2013
Jennifer
Brown
Houston
$100.00
$590.00
$130.2013
I have tried a range of different join options and nested select statements, but cant get this to work. Any ideas please?
We could use analytic functions here, with a two tier aggregation approach:
WITH cte AS (
SUM(Daily_Rate * Total_Paid) OVER (PARTITION BY City) /
SUM(Total_Paid) OVER (PARTITION BY City) AS WA_Rate_City
FROM customer_data
)
SELECT First, Last, City, Daily_Rate, Total_Paid,
MAX(WA_Rate_City) OVER () AS Max_WA_daily
FROM cte;
The first CTE turns out the WA rates partitioned by each city. The query below that finds the max such value, but across the entire table.
Windows functions can be used here. It allows us to have aggregations on different levels within one view [table] which you need.
Additionally, I would suggest not to use Subquery and use Common Table Expressions (CTE)
Step 1: Calculate the weighted average [the one you already did]
Explaination of Step 1:
Here in the OVER() clause you have defined the aggregation level just like you did in the group by above. Which means you can still select all the other colums [first name, last name, daily rate, total paid and NOT have them in the Partition BY clause [the beauty of windows functions]. In windows functions you define the aggregation layer within Partition by which is City in your case)
STEP 2: Get Max() Value [The one you need]
Explaination: here we didn't add the aggregation layer as we just need the max value from the column weighted average.Hence partition by and OVER is left empty
With Weighted_Average AS (
Select
city,
first_name,
last_name,
city,
daily_rate,
total_paid,
sum(daily_rate * total_paid) OVER(PARTITION BY city)
/
sum(total_paid) OVER(PARTITION BY city) AS weighted_average
FROM
customer_data
group by
city
)
Select
*,
MAX(weighted_average) OVER() AS max_weighted_average
FROM
Weighted_Average
select
City,sum(Daily_Rate*Total_paid)/sum(Total_Paid) as WA_Rate
from customer_data
group by City
select ,
(select sum(Daily_RateTotal_paid)/sum(Total_Paid) as WA_Rate from customer_data
where City in ('Dallas')
group by City) as Max_WA_Rate from customer_data
Try the Following
select FistName,LastName,City,Daily_Rate,Total_Paid,
(select max(WA_Rate) from Weight_Average) as Max_Wa_Rate
from customer_data

How to get country wise max populated city with population count

I am currently searching for a SQL query that does the following:
I have a table of all cities worldwide with their countries and population.
e.g. the table "city" (some columns)
name
country
population
Berlin
Germany
3640000
New York
USA
8419000
Hamburg
Germany
1841000
Los Angeles
USA
3967000
I know need to find the city with the city with the highest population per country.
e.g. the desired result
name
population
country
Berlin
3640000
Germany
New York
8419000
USA
The problem is that this query:
SELECT name, MAX(population) FROM city GROUP BY country
wouldn't return the appropriate name of the city. I know why that happens but am not sure how I could solve it in another way.
Any help is appreciated! Thanks!
ANSI SQL solution using subquery almost for any rdbms:
create table city (name varchar(50),country varchar(50), population int);
insert into city values('Berlin' ,'Germany', 3640000);
insert into city values('New York' ,'USA', 8419000);
insert into city values('Hamburg' ,'Germany', 1841000);
insert into city values('Los Angeles' ,'USA', 3967000);
Query:
select name, population, country from city c
where population=(select max(population ) from city a where a.country=c.country)
Output:
name
population
country
Berlin
3640000
Germany
New York
8419000
USA
db<fiddle here
you need to tag your dbms , but this works in most of databases including mariadb , using window function will ovoid hitting city table twice:
select * from
(
select * , row_number() over (partition by country order by population desc) rn
from city
) t
where rn = 1
you can use "NOT EXISTS"
SELECT * from country a
where not exists
(
select 1 from country b
where a.country = b.country
and b.population > a.population
)
select * from city where (country, population) in
(
select country, max(population) from city group by country
);

How to find people in a database who live in the same cities?

I'm new to SQL, and I'm asking for help in an apparently easy question, but it gets cumbersome in my mind.
I have the following table:
ID NAME CITY
---------------------
1 John new york
2 Sam new york
3 Tom boston
4 Bob boston
5 Jan chicago
6 Ted san francisco
7 Kat boston
I want a query that returns all the people who live in a city that another person registered in the database also lives in.
The answer, for the table I showed above, would be:
ID NAME CITY
---------------------
1 John new york
2 Sam new york
3 Tom boston
4 Bob boston
7 Kat boston
This is really a two part question:
What cities have more than one user located in them?
What users live in that subset of cities?
Let's answer it in two parts. Let's also make the simplifying assumption (not stated in your question) that the Users table has only one entry per user per city.
To find cities with more than one user:
SELECT City FROM Users GROUP BY City HAVING COUNT(*) > 1
Now, let's find all the users for those cities:
SELECT ID, User, City FROM Users
WHERE City IN (SELECT City FROM Users GROUP BY CITY HAVING COUNT(*) > 1)
I would use EXISTS :
SELECT t.*
FROM table t
WHERE EXISTS (SELECT 1 FROM table t1 WHERE t1.city = t.city AND t1.name <> t.name);
To avoid a correlated subquery which leads to a nested loop, you could perform a self join:
SELECT id, name, city
FROM persons
JOIN (SELECT city
FROM persons
GROUP BY city HAVING count(*) > 1) AS cities
USING (city);
This might be the most performant solution.
This will give you the rows that have the same city more than 1 time:
SELECT persons.*
FROM persons
WHERE (SELECT COUNT(*) FROM persons AS p GROUP BY CITY HAVING p.CITY = persons.CITY) > 1
This is just a different flavor from the others that have posted.
SELECT ID,
name,
city
FROM (SELECT DISTINCT
ID,
name,
city,
COUNT(1) OVER (PARTITION BY city) AS cityCount
FROM table) t
WHERE cityCount > 1
This can be expressed many ways. Here is one possible way:
select * from persons p
where exists (
select 1 from persons p2
where p2.city = p.city and p2.name <> p.name
)

Getting sub data from a list of facilities

I am trying to write a query and would like some help if possible. Thanks in advance.
I have a table of facility data (~100k rows) that I am getting from a public source. That data contains several records for what I would consider to be the same place (same name, city, state), they just have different suite numbers. The other interesting bit of code is that I have a selection counter on the data that I increment anytime someone chooses one of the facilities. This way, I can use the selection count along with some other weight calculations to make results show higher in a list.
What I am trying to do is write a query that when someone enters a search query, it will show only one record for the facility, the one with the highest selection count, and omit the rest.
Note: I do not want to do any preprocessing to the data as it is going to get re-loaded monthly.
Scheama:
ID
Name
Address 1
Address 2
City
State
Zip
Phone
Selection Count
Example Search: "women"
ID Name City State Selection Count
1 Brigham & Women's Hospital Boston MA 22
2 Brigham & Women's Hospital Cambridge MA 0
3 Brigham & Women's Hospital Boston MA 5
4 Brigham & Women's Hospital Boston MA 1
5 Brigham & Women's Hospital Orlando FL 3
6 Woman's Hospital of Detroit Detroit MI 100
7 Brigham & Women's Hospital Boston MA 0
8 Woman's Hospital of Detroit Detroit MI 55
What I'd like is a resultset that contains 1, 2, 5, 6
1,3,4,7 Are the same so bring back the top selection count. Same for 6 and 8.
I am sure that there is a having and a top clause in here somewhere, but I have not been able to get this to do what I want.
Thoughts?
How about
select id, name, city, state, selcount from t
where exists
(
select 1 from
(select name, city, state, max(selcount) selcount
from t
group by name, city, state) s
where s.name = t.name and s.city = t.city and s.state = t.state and s.selcount = t.selcount
)
I've built a SQL Fiddle for this to show a working example.
WITH cteRowNum AS (
SELECT ID, Name, City, State, [Selection Count],
ROW_NUMBER() OVER(PARTITION BY Name, City, State ORDER BY [Selection Count] DESC) AS RowNum
FROM YourTable
)
SELECT ID, Name, City, State, [Selection Count]
FROM cteRowNum
WHERE RowNum = 1;