I have got 2 tables: Institute & Course
Institute
---------
i_id i_name i_city
------ -------- --------
1 Name 1 London
2 Name 2 Manchester
3 Name 3 London
Course
-------
c_id i_id stream
------ ------- --------
1 1 Engineering
2 1 Engineering
3 2 Engineering
4 3 Engineering
Now I am trying to achieve 3 things:
a) Number of Institutes per city offering Engineering courses.
b) Total (distinct) Number of Institutes offering Engineering courses.
I started writing below query to achieve this:
SELECT institute.i_city,
COUNT( DISTINCT institute.i_id ) AS institute_count_per_city
FROM institute, course
WHERE institute.i_id = course.i_id
AND course.stream = 'Engineering'
GROUP BY institute.i_city
I got below result:
i_city institute_count_per_city
------- -------------------------
London 2
Manchester 1
Now I have achieved the count of institutes per city.
I can't figure how can I get the total number of institutes in same query which in the above example will be 3 (2+1)
I would really appreciate the help.
Use ROLLUP:
SELECT institute.i_city,
COUNT( DISTINCT institute.i_id ) AS institute_count_per_city
FROM institute, course
WHERE institute.i_id = course.i_id
AND course.stream = 'Engineering'
GROUP BY institute.i_city WITH ROLLUP
It will add additional row with SUM of your aggregated values.
Update
GrandTotal version:
SELECT IFNULL(institute.i_city, 'GrandTotal'),
COUNT( DISTINCT institute.i_id ) AS institute_count_per_city
FROM institute, course
WHERE institute.i_id = course.i_id
AND course.stream = 'Engineering'
GROUP BY institute.i_city WITH ROLLUP
Would a union query help?
your existing query
union
select 'total' I_city, count(*) institute_count_per_city
FROM institute, course
WHERE institute.i_id = course.i_id
AND course.stream = 'Engineering'
GROUP BY 'total'
Related
One of the test questions came by with following schemas, to look for the best doctor in terms of:
Best scored;
The most times/attempts;
For each medical procedures (in terms of name)
[doctor] table
id
first_name
last_name
age
1
Phillip
Singleton
50
2
Heidi
Elliott
34
3
Beulah
Townsend
35
4
Gary
Pena
36
5
Doug
Lowe
45
[medical_procedure] table
id
doctor_id
name
score
1
3
colonoscopy
44
2
1
colonoscopy
37
3
4
ulcer surgery
98
4
2
angiography
79
5
3
angiography
84
6
3
embolization
87
and list goes on...
Given solution as follow:
WITH cte AS(
SELECT
name,
first_name,
last_name,
COUNT(*) AS procedure_count,
RANK() OVER(
PARTITION BY name
ORDER BY COUNT(*) DESC) AS place
FROM
medical_procedure p JOIN doctor d
ON p.doctor_id = d.id
WHERE
score >= (
SELECT AVG(score)
FROM medical_procedure pp
WHERE pp.name = p.name)
GROUP BY
name,
first_name,
last_name
)
SELECT
name,
first_name,
last_name
FROM cte
WHERE place = 1;
It'll mean a lot to be clarified on/explain on how the WHERE clause worked out under the subquery:
How it worked out in general
Why must we match the two pp.name and p.name for it to reflect the correct rows...
...
WHERE
score >= (
SELECT AVG(score)
FROM medical_procedure pp
WHERE pp.name = p.name)
...
Thanks a heap!
Above is join with doctor and medical procedure and group by procedure name and you need doctor names with most attempt and best scored.
Subquery will join by procedure avg score and those who have better score than avg will be filtered.
Now there can be multiple doctor better than avg so taken rank by procedure count so most attempted will come first and then you taken first to pick top one
--
I have the following MySQL query :
--
SELECT CONCAT(COALESCE(customer.last_name,''), ' ', COALESCE(customer.first_name,''))
as fullName,
customer.first_name, customer.last_name, customer.email,
address.phone, customer.customer_id
FROM repairs
LEFT JOIN customer
ON customer.customer_id = repairs.customer_id
LEFT JOIN address
ON address.address_id = customer.address_id
WHERE CONCAT(COALESCE(customer.first_name,''), ' ', COALESCE(customer.last_name,'')) LIKE :search
OR CONCAT(COALESCE(customer.last_name,''), ' ', COALESCE(customer.first_name,'')) LIKE :search
OR customer.business_name LIKE :search OR customer.email LIKE :search OR address.phone LIKE :search
GROUP BY fullName
ORDER BY fullName ASC
LIMIT 15
Here's also some data :
(customer table)
customer_id | last_name | first_name | email | address_id
1 Vandalay Art van#gmail.com 2
2 Vandalay Art van123y#yahoo.com 3
3 Dude George george79#gmail.com 4
4 Christian Forge chrfrg#gmail.com 5
(address table)
address_id | address | phone
2 1st Art Institute, 23 +44392031
3 24 Oak Street, Berkl. +62342354
4 51st Main, California +662341232
(repairs table)
repair_id| customer_id | other fields
1 1 ...
2 1 ...
3 1 ...
4 2 ...
5 2 ...
6 1 ...
7 3 ...
8 3 ...
9 2 ...
The tables I'm using are repairs, customer and address.
I use CONCAT on customer.last_name and customer.first_name to generate the full name on which I'm searching, and COALESCE, because sometimes one of them is NULL.
If there happens to be 2 people with the same first and last name, but different address and email, my query will ONLY display one of them, because I Group ON the fullName, and will point me to just one of the two people (and to its client_id).
I need to get back with my query DISTINCT names, but when address / email is different for 2 people with the same name, I need to have both people included (showing the 2 different addresses). So I guess no Group BY...but using DISTINCT.
Sample of DESIRED output :
1 Vandalay Art van#gmail.com
2 Vandalay Art van123y#yahoo.com
3 Dude George george79#gmail.com
4 Christian Forge chrfrg#gmail.com
..so unique names, but I need duplicates if people "happen to have the same name, but actually are 2 different persons"
So far I get only one Art Vandalay, because I Group BY full name....
Any help is appreciated.
I essentially like to have one query which I'll execute one time and like to have the result (no multiple query execution) and definitely, the query should use simple MySQL structure (no complex/advanced structure to be used like BEGIN, loop, cursor).
Say I've two tables.
1st Table = Country (id(PK), name);
2nd Table = Businessman (id(PK), name, city, country_id(FK))
Like to SELECT all countries, whose businessmen are from distinct cities. No two businessmen exist in one country, who are from the same city. If so, that country will not be selected by the SELECT clause.
Country
id name
1 India
2 China
3 Bahrain
4 Finland
5 Germany
6 France
Businessman
id name city country_id
1 BM1 Kolkata 1
2 BM2 Delhi 1
3 BM3 Mumbai 1
4 BM4 Beijing 2
5 BM5 Paris 6
6 BM6 Beijing 2
7 BM7 Forssa 4
8 BM8 Anqing 2
9 BM9 Berlin 5
10 BM10 Riffa 3
11 BM11 Nice 6
12 BM12 Helsinki 4
13 BM13 Bremen 5
14 BM14 Wiesbaden 5
15 BM15 Angers 6
16 BM16 Sitra 3
17 BM17 Adliya 3
18 BM18 Caen 6
19 BM19 Jinjiang 2
20 BM20 Tubli 3
21 BM21 Duisburg 5
22 BM22 Helsinki 4
23 BM23 Kaarina 4
24 BM24 Bonn 5
25 BM25 Kemi 4
In this respect, China and Finland shouldn't be listed.
I've attempted using count and group by, but no luck.
Can you please help me to build up this query.
Here it is, all you need is to join Businessman table and count cities and distinct cities and if they equal that means all businessmen are from different cities:
SELECT
c.`id`,
c.`name`,
COUNT(b.`id`) AS BusinessmanCount,
COUNT(b.`city`) AS CityCount,
COUNT(DISTINCT b.`city`) AS DistinctCityCount
FROM `countries` c
INNER JOIN Businessman b ON c.`id` = b.`country_id`
GROUP BY c.`id`
HAVING CityCount = DistinctCityCount
For minified version what you exactly need:
SELECT
c.`id`,
c.`name`
FROM `countries` c
INNER JOIN Businessman b ON c.`id` = b.`country_id`
GROUP BY c.`id`
HAVING COUNT(b.`city`) = COUNT(DISTINCT b.`city`)
Well, I think we should have waited for you to show your own query, because one learns best from mistakes and their explanations. However, now that you've got answers already:
Yes, you need group by and count. I'd group by cities to see if I got duplicates. Then select countries and exclude those that have duplicate cities.
select *
from country
where id not in
(
select country_id
from businessmen
group by city, country_id
having count(*) > 1
);
You need either nested aggregations:
select *
from Country
where id in
(
select country_id
from
(
select city, country_id,
count(*) as cnt -- get the number of rows per country/city
from Businessman
group by city, country_id
) as dt
group by country_id
having max(cnt) = 1 -- return only those countries where all counts are unique
)
Or compare two counts:
select *
from Country
where id in
(
select country_id
from Businessman
group by country_id
having count(*) = count(distinct city) -- number of cities is equal to umber of rows
)
My question is asking me to count the amount of students within each major. my code...
Select Stu_Major, (Select COUNT(Stu_Major) FROM Student) AS TOTAL
FROM Student
GROUP BY Stu_Major;
counts the total amount of people in all and my output looks like this
STU_MAJOR TOTAL
---------- ----------
CIT 8
Accounting 8
BIS 8
Marketing 8
Statistics 8
but i need it to look like this
STU_MAJOR TOTAL
---------- ----------
CIT 1
Accounting 2
BIS 2
Marketing 2
Statistics 1
and im not sure how to make my code do that.
No need for a subquery:
Select Stu_Major, COUNT(*)
FROM Student
GROUP BY Stu_Major
Having two tables in my database, it's like
Department
//Department
D# DNAME
---------------
1 RESEARCH
2 IT
3 SCIENCE
PROJECT
//Project
Budget D#
---------------
22500 1
22300 1
50000 2
So i using this statement
SELECT D#,DNAME and sum(budget) as total budget
FROM DEPARTMENT,PROJECT
GROUP BY D#;
my output should be like, if a department don't have any project budget mean display 0
D# DNAME total budget
-------------------------------
1 RESEARCH 44800
2 IT 50000
3 SCIENCE 0
You are missing your where clause:
SELECT d.D#,DNAME and sum(budget) as total budget
FROM DEPARTMENT d, PROJECT p
where d.d# = p.dt#
GROUP BY d.D#;
Or to include departments without budget:
SELECT d.D#,DNAME and sum(budget) as total budget
FROM DEPARTMENT d
left outer join PROJECT p
on d.d# = p.d#
GROUP BY d.D#;
This might help you
SELECT `D#`,`DNAME`,
IFNULL((SELECT sum(`budget`)
FROM `project` WHERE `project.`D#` = `Department`.`D#` ),0) AS `total budget`
FROM `Department`
If you execute EXPLAIN on this query, you might notice, that it uses indexes more efficient then queries with GROUP BY