Trying to run a subquery in Postgres - sql

Trying to get a subquery going to find out which countries have more than 20 cities in this database (the dvdrental database from postgres). I am getting a syntax error message for "SELECT COUNT(c.city)" any idea to help fix it would be appreciated.
SELECT *
FROM g
(SELECT COUNT(c.city) AS number_cities, co.country
FROM city c
JOIN country co
ON c.country_id= co.country_id
GROUP BY co.country
ORDER BY country)g
WHERE COUNT(c.city)>=20

The problem is the g in select * from g
it should be
SELECT * FROM (
SELECT COUNT(c.city) AS number_cities, co.country
FROM city c
JOIN country co ON c.country_id= co.country_id
GROUP BY co.country ORDER BY country) g
WHERE number_cities>= 20
or you can remove the subquery, and use having instead
SELECT COUNT(c.city) AS number_cities, co.country
FROM city c
JOIN country co ON c.country_id= co.country_id
GROUP BY co.country
HAVING COUNT(c.city)>=20
ORDER BY country

Related

Why Oracle OFFSET and LIMIT is not working when using DISTINCT

I need to get clarified the below situation.
I have a city, country table and I need to validate this will some other tables and get the city country results ordered by the country. Here's my query for that
SELECT distinct
c.code as CITY ,
c.country as COUNTRY from location_info li
inner join someTable s on li.loc_id = s.some_id
inner join city c on s.city = c.code
ORDER BY c.country
And this provides the results as
Now when I use OFFSET and LIMIT values in the below query
SELECT distinct
c.code as CITY,
c.country as COUNTRY from location_info li
inner join someTable s on li.loc_id = s.some_id
inner join city c on s.city = c.code
ORDER BY c.country OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY.
I expect to get ADOR, ADPC, ADSJ, ADVD, ALV as the output.
Why is that and what I am missing here in this query.
When I do the following I get the expected outcome
SELECT CITY, COUNTRY FROM ( SELECT distinct
c.code as CITY,
c.country as COUNTRY from location_info li
inner join someTable s on li.loc_id = s.some_id
inner join city c on s.city = c.code
ORDER BY c.country ) OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY.
The issue is that the ORDER BY is not stable. What that means is that you have ties in the key values. So, running the query two times might result in different orderings.
This is easily fixed by including more keys in the order by so the order by keys uniquely identify each row:
select distinct c.code as CITY, c.country as COUNTRY
from location_info li join
someTable s
on li.loc_id = s.some_id join
city c
on s.city = c.code
order by c.country, c.code;

SQL JOIN returns more records than expected

I have the table:
Country city population
------------------------
Israel RG 100
Israel TA 300
US NY 900
US SF 700
In order to get for each country the max population I am running the below query:
select Country, max(population) as maxPopulation
from A
group by Country
I want to get full output:
Country city population
-----------------------
Israel TA 300
US NY 900
In order to do it I need to join on the full table - please correct me if I am wrong.
select A.Country, A.city, A.population
from A
right join
(select Country, max(population) as maxPopulation
from A
group by Country) temp on temp.Country = A.Country
This returns all the 4 records... instead of 2...
You can use correlated subquery :
select a.*
from a
where population = (select max(a1.population) from a a1 where a1.Country = a.Country);
For your JOIN query version, you need one more condition that is . . . and temp.maxPopulation = A.Population & why you need right join here only inner join is sufficient :
select a.*
from a inner join
(select Country, max(population) as maxPopulation
from a
group by Country
) temp
on temp.Country = a.Country and temp.maxPopulation = a.population;
I would use a standard CTE:
with
x as (
select country, max(population) as pop from A group by country
)
select A.*
from A
join x on x.country = A.country and x.pop = A.population
A [desirable?] side effect of this query, is that if there are multiple cities with the same max population it will show them all.

Display the city name which has most number of branches

I have tried to get city name which has most number of branches .
select C.City_name ,count(B.B_Name)
from tblcity C
inner join
tblBranch B
on c.city_id=B.City_id
group by C.City_name
order by count(B.B_Name) desc
Above code will give me the count of branches for particular city .
Please help me solve to get city name which has most number of branches
you can add TOP 1 to your query
select TOP 1 C.City_name ,count(B.B_Name)
from tblcity C
inner join
tblBranch B
on c.city_id=B.City_id
group by C.City_name
order by count(B.B_Name) desc
Use DENSE_RANK():
SELECT
City_Name, cnt
FROM
(
SELECT
c.City_name,
COUNT(b.B_Name) cnt,
DENSE_RANK() OVER (ORDER BY COUNT(b.B_Name) DESC) dr
FROM tblcity c
INNER JOIN tblBranch b
ON b.city_id = c.City_id
GROUP BY c.City_name
) t
WHERE dr = 1;
Using TOP 1 WITH TIES would be another option here, but that is specific to SQL Server.

Using a subquery with inner join in the from clause?

I'm trying to create a table that with one column containing the number of countries and the next column being the number of official countries. So basically, one row might say there are 32 countries that have 2 official languages, 28 with 3 official languages, etc.
So far I've made a table that counts the number of official languages per each individual country.
select c.name, count(l.language) number_of_languages from world.country c
inner join (select countrycode, language, isofficial from
world.countrylanguage where isofficial='T') l on c.code=l.countrycode group
by c.name order by count(l.language)
Here's a sample of the result:
NAME NUMBER_OF_LANGUAGES
---------------------------------------------------- -------------------
Lesotho 2
Sri Lanka 2
Canada 2
Singapore 3
Belgium 3
Bolivia 3
First, your query can be simplified. It doesn't need to use a subquery:
select c.name, count(cl.language) as number_of_languages
from world.country c inner join
world.countrylanguage cl
on c.code = cl.countrycode
where cl.isofficial = 'T'
group by c.name
order by count(cl.language);
Next, use this as a subquery:
select number_of_languages, count(*)
from (select c.name, count(cl.language) as number_of_languages
from world.country c inner join
world.countrylanguage cl
on c.code = cl.countrycode
where cl.isofficial = 'T'
group by c.name
) cl
group by number_of_languages
order by number_of_languages;

How to sort by count with postgresql?

I have two tables:
Companies: (id, name, city)
Workers: (id, name)
I would like to get all companies and sort them by numbers of employes.
The result should give:
count | company id | company name | city
------------------------------------------
90 6 foo corp NY
45 9 bar corp LA
0 3 foobar corp HO
I tried:
select
c.*,
count(w.id) as c
from
companies c
left join
workers w
on
c.id = w.company_id
group by
c.id
order by
c desc;
But that's not working as it tells me to group by g.name too :/
Any ideas?
You've aliased the table and column as the same thing, so don't do that. It's not invalid, just tough to follow.
Anyway, include all columns that you're selecting that aren't aggregates in your group by:
select
count(w.id) as mycount,
w.company_id,
c.company_name,
c.city
from
companies c
left join workers w on
c.id=w.company_id
group by
w.company_id,
c.company_name,
c.city
order by mycount desc;
If you don't want the count result to be returned (because of an ORM framework or so), you could apply it directly in the order by clause:
select
c.*
from
companies c
left join
workers w
on
c.id = w.company_id
group by
c.id
order by
count(w.id) desc;
Tested with postgreSQL 11
Try this as a subquery:
SELECT C.*
FROM
(
SELECT C.Id, C.Company_Name, C.City, COUNT(W.Id) AS CNT
FROM Companies C
LEFT JOIN Workers W ON W.Company_Id = C.Id
GROUP BY C.Id, C.Company_Name, C.City
) T
ORDER BY T.CNT