Lets say I have the following tables:
Countries
---------------------------
| ID | Country Name |
---------------------------
| 1 | Greece |
| 2 | Italy |
| 3 | Spain |
---------------------------
Cities
---------------------------
| ID | City |
---------------------------
| 1 | Athens |
| 2 | Patra |
| 3 | Rome |
| 4 | Venice |
---------------------------
Countries & Cities
--------------------
| ID | Cntr | City |
--------------------
| 1 | 1 | 2 |
| 2 | 1 | 1 |
| 3 | 2 | 3 |
--------------------
Now, How can I run a MySQL query that will return the name of the countries and the total cities based on table "Countries & Cities" ?
In example to return:
---------------------------
| Cities | Country |
---------------------------
| 2 | Greece |
| 1 | Italy |
---------------------------
Try this out:
SELECT COUNT(cs.City) as Cities, cn.name as Country
FROM countries cn
INNER JOIN country_city cs ON cs.Cntr = cn.id
GROUP BY cn.name
OUTPUT:
2 | Greece
1 | Italy
There is only one JOIN is needed
SELECT `c`.`name`, COUNT(`c`.id)
FROM `countries_cities` AS `cc`
JOIN `countries` AS `c`
ON `c`.id = `cc`.country_id
GROUP BY `cc`.country_id
SELECT cn.Name, COUNT(*)
FROM CountriesAndCities cc
JOIN Countries cn ON (cn.ID = cc.Cntr)
GROUP BY cn.Name
You only need to group the countries in the countries & cities table:
SELECT COUNT(1), c.Name
FROM [countriesAndCities] cnc
INNER JOIN [country] c ON cnc.cnt = c.id
GROUP BY c.Name
Related
These are the tables I am fetching count from
register
+----+-------------+--------+
| id | empSignupId | cityId |
+----+-------------+--------+
| 42 | 4 | 1 |
| 47 | 3 | 1 |
| 48 | 11 | 1 |
| 54 | 20 | 1 |
| 55 | 21 | 2 |
| 56 | 22 | 2 |
+----+-------------+--------+
guest_list
+-----+------------+-------------+
| id | guestName | empSignupId |
+-----+------------+-------------+
| 103 | Mallica SS | 3 |
| 104 | Kavya | 3 |
| 108 | Vinay BR | 11 |
| 109 | Akash MS | 11 |
+-----+------------+-------------+
cities
+----+---------------+
| id | cityName |
+----+---------------+
| 1 | Bengaluru |
| 2 | Chennai |
| 3 | Sydney |
| 4 | New York City |
| 5 | Shanghai |
| 6 | Chicago |
+----+---------------+
I need to fetch the count of people registered from particular city which includes people, their guests, if guests are not present also it should show the count of people.
This is what I tried
SELECT COUNT(gl.id) + COUNT(rfs.id), ct.cityName, rfs.cityId
FROM register rfs
INNER JOIN cities ct ON ct.id=rfs.cityId
INNER JOIN guest_list gl ON gl.empSignupId = rfs.empSignupId
GROUP BY rfs.cityId;
+-------------------------------+-----------+--------+
| COUNT(gl.id) + COUNT(rfs.id) | cityName | cityId |
+-------------------------------+-----------+--------+
| 8 | Bengaluru | 1 |
+-------------------------------+-----------+--------+
I also need the count of people from other cities to be displayed, since there are no guests from some cities its not returning that count.
Please help me figure this out, I am still new to MySQL.. any help is greatly appreciated.
You fist need to aggregate guest_list table in order to get the number of records per empSignupId:
SELECT empSignupId, COUNT(empSignupId) AS countGuest
FROM guest_list gl
GROUP BY empSignupId
Output:
empSignupId countGuest
----------------------
3 2
11 2
Now you have to use a LEFT JOIN to the derived table above in order to also get the number of records for each city:
SELECT COALESCE(SUM(countGuest), 0) + COUNT(rfs.id), ct.cityName, rfs.cityId
FROM register rfs
INNER JOIN cities ct ON ct.id=rfs.cityId
LEFT JOIN (
SELECT empSignupId, COUNT(empSignupId) AS countGuest
FROM guest_list gl
GROUP BY empSignupId
) gl ON gl.empSignupId = rfs.empSignupId
GROUP BY rfs.cityId;
Output:
COALESCE(SUM(countGuest), 0) + COUNT(rfs.id) cityName cityId
------------------------------------------------------------------
8 Bengaluru 1
2 Chennai 2
Using LEFT JOIN instead of INNER JOIN guarantees that we also get cities without guests.
Demo here
Note: If you also want to get cities without registrations then you need to place the cities table first and use a LEFT JOIN to register.
Use LEFT JOINS and add count(distinct r.empSignupId) + count(distinct g.id):
select
c.id as cityId,
c.cityName,
count(distinct r.empSignupId) + count(distinct g.id) as people_count
from cities c
left join register r on r.cityId = c.id
left join guest_list g on g.empSignupId = r.empSignupId
group by c.id;
The result would be:
| cityId | cityName | people_count |
|--------|---------------|--------------|
| 1 | Bengaluru | 8 |
| 2 | Chennai | 2 |
| 3 | Sydney | 0 |
| 4 | New York City | 0 |
| 5 | Shanghai | 0 |
| 6 | Chicago | 0 |
Demo: http://rextester.com/OTBH14189
If you don't need the rows with 0, change the first LEFT JOIN to an inner JOIN.
I have a PostgreSQL database linked to a Drill instance.
Whenever I am trying to join 2 tables which both have a column name and whenever I want to select this name Drill selects the wrong name column. What am I doing wrong?
Given the following 2 tables:
Department
| id | name |
|----|------|
| 1 | A |
| 2 | B |
Employee
| id | name | dept | salary |
|----|------|------|--------|
| 1 | U | 1 | 100 |
| 2 | V | 1 | 75 |
| 3 | W | 1 | 120 |
| 4 | X | 2 | 95 |
| 5 | Y | 2 | 140 |
| 6 | Z | 2 | 55 |
Running
select employee.name, employee.salary
from employee
inner join department on employee.dept = department.id
where department.name = 'A'
returns
| name | salary |
|------|--------|
| A | 100 |
| A | 75 |
| A | 120 |
Running
select dept.name, employee.salary
from employee
inner join department on employee.dept = department.id
where department.name = 'A'
returns
| name | salary |
|------|--------|
| null | 100 |
| null | 75 |
| null | 120 |
What does work, but seems very silly to me, is:
select dept.name, employee.salary
from employee
inner join (select id, name as deptname from department) as department on employee.dept = department.id
where department.deptname = 'A'
This seems to be because you use
select dept.name, [...]
But you have never assigned an alias for the table department (department AS dept). Hence
select department.name, [...]
should yield the value you are looking for.
I have 2 tables with the below structure where there is no relation of (PK / FK).
======== country =======
+----+-------+---------+
| id | name | visible |
+----+-------+---------+
| 1 | kkk | 0 |
| 2 | mmm | 1 |
| 3 | ttt | 1 |
| 4 | kkkkk | 0 |
+----+-------+---------+
============ city =============
+----+------+---------+-------+
| id | name | visible | c_id |
+----+------+---------+-------+
| 3 | k333 | 0 | 1 |
| 2 | k222 | 1 | 1 |
| 1 | kkk | 1 | 1 |
| 4 | k444 | 0 | 2 |
| 6 | k666 | 0 | 2 |
+----+------+---------+-------+
I am using country.id and city.country_id as the link between the 2 tables. I am trying to delete the countries and cities where visibility value is 0. After searching I came up with this piece of code:
delete country , city from country, city where city.country_id = country.id and country.id in (select id from country where visible = 0);
But it returns the below error:
ERROR 1093 (HY000): You can't specify target table 'country' for update in FROM clause
I tried to use JOIN with WHERE like this :
DELETE country , city
FROM country JOIN city
ON city.country_id = country.id
WHERE country.visible = 0
It worked well, but there is one more row which is having the value of 0 was not deleted.
======== Country ======
+----+-------+---------+
| id | name | visible |
+----+-------+---------+
| 2 | mmm | 1 |
| 3 | ttt | 1 |
| 4 | kkkkk | 0 |
+----+-------+---------+
#Mihai After I checked your code again I just added WHERE and it worked like this:
DELETE country, city
FROM country
LEFT JOIN city
ON city.country_id = country.id
WHERE country.visible = 0;
Use a JOIN with a WHERE, it is much clearer.
DELETE country , city
FROM country JOIN city
ON city.country_id = country.id
WHERE country.visible = 0
ON your sample data the kkk row with visible=0 wont be deleted since it has an id of 4 which doenst exist in the city table so it won`t be picked up in the join.
I have the following so far:
SELECT D.department AS dept, C.name AS subdept
FROM (SELECT DISTINCT department FROM classes WHERE web != 0 ORDER BY department,name LIMIT 5) D
LEFT JOIN classes C ON (C.department = D.department)
ORDER BY D.department,C.name
Which results in something like:
+------+-------------------------------+
| dept | subdept |
+------+-------------------------------+
| BOOK | CHILDRENS BOOKS |
| BOOK | DVD'S |
| CLOT | ACCESSORIES |
| CLOT | APRONS |
| FEED | BIBS & BURP CLOTHS |
| FEED | BOTTLE & FOOD WARMERS |
+------+-------------------------------+
What Im trying to get is a 'header' for the each department with a null subdept value such as:
+------+-------------------------------+
| dept | subdept |
+------+-------------------------------+
| BOOK | null |
| BOOK | CHILDRENS BOOKS |
| BOOK | DVD'S |
| CLOT | null |
| CLOT | ACCESSORIES |
| CLOT | APRONS |
| FEED | null |
| FEED | BIBS & BURP CLOTHS |
| FEED | BOTTLE & FOOD WARMERS |
+------+-------------------------------+
The structure of the tables: departments table has id primary key to classes department field as foreign key.
Departmens: id | name (of department)
Classes: department | name (of class)
Based on what DanfromGermany has shown me I have:
SELECT D.department AS dept, C.name AS subdept
FROM
(SELECT DISTINCT department FROM classes WHERE web != 0 ORDER BY department,name LIMIT 5) D
LEFT JOIN classes C ON (C.department = D.department)
GROUP BY D.department, C.name WITH ROLLUP
Which now gives:
+--------+-------------------------------+
| dept | subdept |
+--------+-------------------------------+
| BOOK | CHILDRENS BOOKS |
| BOOK | DVD'S |
| BOOK | [NULL] |
| CLOT | ACCESSORIES |
| CLOT | APRONS |
| CLOT | [NULL] |
| FEED | BIBS & BURP CLOTHS |
| FEED | BOTTLE & FOOD WARMERS |
| FEED | [NULL] |
| GEAR | BOOSTER CAR SEATS |
| GEAR | CAR SEAT ACCESSORIES |
| GEAR | [NULL] |
| GIFT | BABY BASKETS & DIAPER CAKES |
| GIFT | BANKS |
| GIFT | [NULL] |
| [NULL] | [NULL] |
+--------+-------------------------------+
OK last edit:
It works by subquery to use order by:
SELECT * FROM
(SELECT D.department AS dept, C.name AS subdept
FROM
(SELECT DISTINCT department FROM classes WHERE web != 0 ORDER BY department,name LIMIT 5) D
LEFT JOIN classes C ON (C.department = D.department)
GROUP BY D.department, C.name WITH ROLLUP
) T
ORDER BY dept,subdept
Change your query to have a GROUP BY clause,
then use WITH ROLLUP.
See in the middle of that page:
http://dev.mysql.com/doc/refman/5.1/en/group-by-modifiers.html
Or google for "GROUP BY WITH ROLLUP mysql"
Something like this (untested):
SELECT D.department AS dept, C.name AS subdept
FROM
(SELECT DISTINCT department FROM classes WHERE web != 0 ORDER BY department,name LIMIT 5) D
LEFT JOIN classes C ON (C.department = D.department)
GROUP BY dept, subdept WITH ROLLUP
ORDER BY D.department,C.name
Suppose I have two tables:
Customers
Name | id |
-------------------
Benny | 1 |
Wilson | 2 |
Joe | 3 |
Austin | 4 |
Orders
Product | id |
---------------------
TV | 1 |
Hifi-set | 1 |
HTPC | 1 |
CD | 1 |
DVD | 1 |
CD | 1 |
DVD | 1 |
And this is what I want with the results:
Name | Orders |
-------------------
Benny | 7 |
Wilson | 0 |
Joe | 0 |
Austin | 0 |
I'm not familiar with SQL, But I tried:
SELECT c.Name FROM Customers AS c LEFT JOIN Orders AS o ON c.id=o.id GROUP BY c.Name
But got a wrong result:
Name | Orders |
-------------------
Benny | 4 |
Wilson | 1 |
Joe | 1 |
Austin | 1 |
What do I do?
Try:
select
c.Name,
(select count(1) from Orders where ID=c.ID)
from
Customers as c
By not using SubQuery, you can also JOIN instead.
SELECT a.Name, COUNT(b.id)
FROM Customers a LEFT JOIN Orders b
on a.ID = b.ID
GROUP BY a.Name