There are 3 types of adventures for which I used distinct function in query.
There is only one 1 customer who have booked all types of adventures.
The query i used to fetch the data is:
select c.customerid,c.name
from customer c
inner join booking b
on c.customerid = b.customerid
inner join destination d
on b.destinationid=d.destinationid
inner join adventure a
on d.adventureid=a.adventureid
group by c.customerid
having count(distinct b.bid)=(select count(*) from bid)
or count(distinct a.adventuretype)=(
select count(distinct a.adventuretype)
from adventure
)
You can get the customer ids using aggregation and having:
select b.customerid
from booking b join
destination d
on b.destinationid = d.destinationid join
adventure a
on d.adventureid = a.adventureid
group by b.customerid
having count(distinct a.advtype) = 3;
Or, if you don't want to hardcode the "3", you can use:
having count(distinct a.advtype) = (select count(distinct advtype from adventure)
I'll leave it up to you to add in the customer name (using join, exists, or in).
I have these 4 tables:
Suppliers(id_sup, name, city)
Companies( id_co, name, city)
Products(id_p, name, city)
Deliveries (id_sup, id_co, id_p)
in one query, I need to get a list of all cities (no duplicates) and for each, show the number of suppliers, companies, and products that can be found in that city.
In oracle SQL I would have used some Full OUTER JOIN. what's the alternative?
This is a suggested solution for joining 2 of the tables:
SELECT city
, COUNT(DISTINCT id_sup) Suppliers
, COUNT(DISTINCT id_co) Companies
FROM ( SELECT COALESCE(s.city,c.city) city
, id_sup
, id_co
FROM Suppliers AS s
LEFT OUTER JOIN Companies AS c ON c.city = s.city
UNION
SELECT COALESCE(s.city,c.city) city
, id_sup
, id_co
FROM Suppliers AS s
RIGHT OUTER JOIN Companies AS c ON c.city = s.city ) AS union_query
GROUP BY city
How to add the final table Products to the mix?
With UNION get all the cities from all 3 tables and LEFT join to the results the 3 tables to finally aggregate:
select t.city,
count(distinct s.id_sup) counter_suppliers,
count(distinct c.id_co) counter_companies,
count(distinct p.id_p) counter_products
from (
select city from suppliers union
select city from companies union
select city from products
) t
left join suppliers s on s.city = t.city
left join companies c on c.city = t.city
left join products p on p.city = t.city
group by t.city
See a simplified demo.
Just use union all and group by:
select city, sum(is_supplier), sum(is_company),
sum(is_product), sum(is_delivery)
from ((select city, 1 as is_suppler, 0 as is_company, 0 as is_product, 0 as is_delivery
from suppliers
) union all
(select city, 0 as is_suppler, 1 as is_company, 0 as is_product, 0 as is_delivery
from companies
) union all
(select city, 0 as is_suppler, 0 as is_company, 1 as is_product, 0 as is_delivery
from products
) union all
(select city, 0 as is_suppler, 0 as is_company, 0 as is_product, 1 as is_delivery
from deliveries
)
) c
group by city;
Or, even more simply in MySQL:
select city, sum(which = 'supplier'), sum(which = 'company'),
sum(which = 'product'), sum(which = 'delivery')
from ((select city, 'suppler' as which from suppliers
) union all
(select city, 'company' as which from companies
) union all
(select city, 'product' as which from products
) union all
(select city, 'delivery' as which from deliveries
)
) c
group by city;
to get all cities, since we don't have a city table as a dimension, we can get the domain from each of the city columns from each of the three tables, and combine them with UNION set operator:
SELECT cs.city
FROM suppliers cs
GROUP BY cs.city
UNION
SELECT cc.city
FROM companies cc
GROUP BY cc.city
UNION
SELECT cp.city
FROM products cp
GROUP BY cp.city
That should get us a list of distinct city values that appear in the three tables.
We could take that set, and do outer join operations to the individual tables. But that has the potential to generate cross product... if there are three suppliers related to a city and four companies related to the same city, we would generate a resultset of twelve rows.
To fix that, we could get a count of DISTINCT primary key values.
Or, we can pre-aggregate the results in inline views, returning a single row per city. That avoids the problem of semi-cartesian products.
Let's reference the query above in an line view in another query. We will alias it ci. (If we had a dimension table city, we could reference that,)
Something like this:
SELECT ci.city
, IFNULL(np.cnt_,0) AS cnt_products
, IFNULL(nc.cnt_,0) AS cnt_companies
, IFNULL(ns.cnt_,0) AS cnt_suppliers
FROM ( /* inline view query */ ) ci
LEFT
JOIN ( SELECT p.city
, COUNT(1) AS cnt_
FROM products p
GROUP BY p.city
) np
ON np.city = ci.city
LEFT
JOIN ( SELECT c.city
, COUNT(1) AS cnt_
FROM companies c
GROUP BY c.city
) nc
ON nc.city = ci.city
LEFT
JOIN ( SELECT s.city
, COUNT(1) AS cnt_
FROM suppliers s
GROUP BY s.city
) ns
ON ns.city = ci.city
ORDER BY ci.city
(In place of /* inline view query */, use the SQL text from the first query, to generate the distinct list of city.)
I have two tables:
Class: cid, name, location
Student: sid, name, gender, classID
I am attempting to use a select statement to display the class name along with the total number of students in the class. I'm also trying to exclude any class with less than 10 students from the table.
SELECT
c.name as className,
count(s.sid) as totalStudents
FROM Class c
JOIN Student s ON s.classID = c.cid
GROUP BY c.id
HAVING count(s.sid) >= 10
select a.name, count(*)
from Class as a
inner join Student as b on b.ClassID = a.cid
group by a.name
having count(*) >= 10;
I am trying to select the classes with maximum enrollment in each department from a table with the following structure:
Courses: cid, dept, name
Enrollment: cid, sid
The idea would be to count all the enrollments in each class, and find the maximum in each department. Unfortunately, I'm having trouble with the maximum-count combination.
My query was going to look something like:
SELECT c.name, MAX(COUNT(*) FROM Enrollment E WHERE E.cid = C.cid)
FROM Courses C
GROUP BY C.dept
But I can't figure out how to get the MAX-COUNT syntax to work properly. I've tried a lot of different examples from Google and StackOverflow and none of them worked for me. MySQL says the syntax is wrong.
I like nested queries for this kind of problem. First select the enrollment counts grouped per class. Then find the max enrollment count grouped per department:
SELECT MAX(cnt) cnt, dept FROM
(
SELECT COUNT(*) cnt, dept, C.cid
FROM Courses C
INNER JOIN Enrollment E on C.cid = E.cid
GROUP BY cid, dept
) a
GROUP BY dept
There is no declaration of E, so you can't use E.cid
So, either you do this
SELECT c.name, COUNT(c.*) as count
FROM Courses C
GROUP BY C.dept
Or,
SELECT c.name, MAX(SELECT COUNT(*) FROM Enrollment E WHERE E.cid = C.cid)
FROM Courses C
GROUP BY C.dept
SELECT MAX(cnt) FROM (
SELECT c.name, COUNT(E.*) AS cnt FROM Enrollment E
INNER JOIN Courses C ON E.cid = C.cid
GROUP BY C.dept
) final
I have a MySQL database with two tables in it:
Members
- id, name, city_id
and:
Cities
- id, name
I want a query that will return each city name and how many members are in it.
The output I need is:
city_name count
------------------
New York 15
Los Angeles 20
something like this:
SELECT a.name, COUNT(DISTINCT b.city_id)
FROM Cities a JOIN Members b
ON b.city_id = a.id
GROUP BY b.city_id
SELECT
c.name AS city_name,
COUNT(m.id) AS counter
FROM Members m
JOIN Cities c ON m.city_id = c.id
select
cities.name as city_name,
count(cities.id) as counter
from
members inner join cities
on
members.city_id = cities.city.id
Try this
SELECT c.name city_name, COUNT(m.id) counter
FROM Cities c INNER JOIN Members m
ON c.id = m.city_id
GROUP BY c.name
Try something like this:
select city.name, count(member.id)
from city
inner join members
on city.id = members.city_id
group by city.name
Hope this helps.