How to sort by count with postgresql? - sql

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

Related

Trying to run a subquery in Postgres

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

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.

Filtering records using rank

I am joining two tables contact and district and the join is returning multiple records for each city. I want to pick anyone record for each city using rank. Following is my query but it is not working. How can I correct my query?
Select p.name,
p.city,
p.district,
RANK() over (partition by p.city order by p.district asc) as rank
from (select
d.name,
c.city,
c.district
from contact c inner join district d
ON d.district = c.district
AND d.districtType ='d'
AND d.nametype='2'
AND c.district like 'E%'
where c.city in(1316,1515,19393,8026))p
rank=1;
where clause is missing before rank =1
Select p.name,
p.city,
p.district,
RANK() over (partition by p.city order by p.district asc) as rank
from (select
d.name,
c.city,
c.district
from contact c inner join district d
ON d.district = c.district
AND d.districtType ='d'
AND d.nametype='2'
AND c.district like 'E%'
where c.city in(1316,1515,19393,8026))p
where rank=1;

SQL - Select only last order for every clients who had ordered before

There are 2 tables, and I want to select only last order for each client that has ordered before...
(cid,cname) Clients table
1 , David
2 , Tom
3 , Alex
(oid,cid,title,ordertime) Orders table
1,1,"Tshirt",2013-10-1
2,3,"Ball",2013-10-1
3,3,"Food",2013-11-20
*Acording to tables Tom never ordered before. So he will not be listed. Alex ordered 2 times before and I want only show last order.
Output must be like this :*
1,1,"Tshirt",2013-10-1, David
3,3,"Food",2013-11-20, Alex
I tried something like this code but Alex was listed 2 times. I dont understand how I can figure out.
select *
from Clients t2
left join Orders t1
on t1.cid=t2.cid
where t1.ordertime<getutcdate()
order by t1.ordertime desc**
Probably I must use Distinct or Group by but I dont understand how.
Select
x.oid,
x.cid,
x.title,
x.ordertime,
x.cname
From (
Select
o.oid,
o.cid,
o.title,
o.ordertime,
c.cname,
row_number() over (partition by o.cid order by o.ordertime desc) rn
From
Clients c
inner join
Orders o
on c.cid = o.cid
) x
Where
x.rn = 1
SELECT o.*, c.name
FROM orders o INNER JOIN clients c on o.cid = c.cid
INNER JOIN (SELECT MAX(oid) as latestOrderid, cid FROM orders GROUP BY cid) as latest
on latest.latestorderid= orders.oid
Try this:
select o.*, c.cname
from clients c
join orders o on
c.cid = o.cid
and not exists (select *
from orders o2
where o2.cid = o.cid
and o2.ordertime > o.ordertime)

How to sort by custom count with postgresql?

I have two tables:
Companies: (id, name)
Workers: (id, name, country)
I would like to get all companies and sort them by numbers of employees from a given country.
For a query looking for companies that have more workers from the USA, the result should give:
#workers from USA | company id | company name
----------------------------------------------
90 6 foo corp
45 9 bar corp
0 3 foobar corp
I tried:
select
count(w.country='USA') as mycount,
w.company_id,
c.company_name
from
companies c
left join workers w on
c.id=w.company_id
group by
w.company_id,
c.company_name
order by mycount desc;
But that's counting all workers regardless of their countries.
Any ideas?
You can do that easily with a correlated subquery:
SELECT
(SELECT count(*) FROM workers w WHERE w.company_id=c.id AND w.country='USA') AS mycount,
c.id,
c.company_name
FROM
companies c
ORDER BY mycount DESC
Does replacing COUNT(w.country='USA') with COUNT(*) help? I believe your query needs to refer to fields on the Companies table as opposed to workers because your left join leaves open the possibility that the set of workers pulled for a specific company/country is the empty set.
Try:
select count(*) as mycount,
c.company_id,
c.company_name
from companies c
left join workers w on c.id=w.company_id
group by c.company_id, c.company_name
order by mycount desc;