Reputation: 61
I have 3 tables: Projects, Components, Suppliers. Each one has an id column, city column and some other columns.
What I am trying to do is count how many projects, components and suppliers there are for each city.
What I have tried is:
SELECT p.city, COUNT(p.idp), COUNT(c.idc), COUNT(s.idf) FROM
Projects p, Components c, Suppliers s
GROUP BY p.city
After running this query, I am getting incorrect values, almost all of them are the same, like it's shown here:
I only have one project, 1 or 2 components and 1-3 suppliers stored for each city so these are not the expected results
After looking for some similar solved problems I came up with this piece of code
SELECT p.city , p.nr_projects, c.nr_components, s.nr_suppliers
FROM
(SELECT city, COUNT(idp) AS nr_projects
FROM Projects
GROUP BY city)
AS p
JOIN
(SELECT city, COUNT(idc) AS nr_components
FROM Components
GROUP BY city)
AS c
ON p.city=c.city
JOIN
(SELECT city, COUNT(idf) AS nr_suppliers
FROM Suppliers
GROUP BY city)
as f
ON p.city=f.city
GROUP BY p.city;
This gave me an error saying that the SQL command was not properly ended.
How should I approach this task?
Upvotes: 1
Views: 53
Reputation: 29677
Union the totals, then aggregate.
That way you'll also have totals for cities that are missing in 1 of the tables.
Which wouldn't be in the result when using INNER JOIN
. (but they would with FULL JOIN
)
SELECT city,
SUM(proj) AS projects,
SUM(comp) AS components,
SUM(supp) AS suppliers
FROM
(
SELECT city
, COUNT(idp) AS proj
, 0 AS comp
, 0 AS supp
FROM Projects
GROUP BY city
UNION ALL
SELECT city, 0, COUNT(idc), 0
FROM Components
GROUP BY city
UNION ALL
SELECT city, 0, 0, COUNT(idf)
FROM Suppliers
GROUP BY city
) q
GROUP BY city
ORDER BY city
Upvotes: 1
Reputation: 147236
Since you are no longer performing any aggregation at the top level of your query, you no longer need a GROUP BY
clause. Also, for Oracle, you cannot use an AS
in the table alias expression. This should work:
SELECT p.city , p.nr_projects, c.nr_components, s.nr_suppliers
FROM
(SELECT city, COUNT(*) AS nr_projects
FROM Projects
GROUP BY city) p
JOIN
(SELECT city, COUNT(*) AS nr_components
FROM Components
GROUP BY city) c ON p.city=c.city
JOIN
(SELECT city, COUNT(*) AS nr_suppliers
FROM Suppliers
GROUP BY city) s ON p.city=s.city
Note that if a city might not have projects, components or suppliers then you should use a FULL OUTER JOIN
in place of JOIN
to ensure you still get rows for that city in the output.
Note also that it is more efficient to use COUNT(*)
than to count a particular variable (as there is no need to check for NULL
values) and I have made that modification to the query.
Upvotes: 2