Find Count of racers from Race Table - mysql

I am new to SQL,I have two tables RACER and SPONSOR,
RACER TABLE has these columns
RACER_NAME,
SPONSOR_ID
RACER_ID- Primary KEY
SPONSOR table has these columns
SPONSOR_ID,
SPONSOR_NAME
now I want to find the SPONSOR name and no.of racer associated with that SPONSOR.
Here is what I tried:
select s.sponsor_name , (select count(*) from racer r) where INNER JOIN s.sponsor_id = r.sponsor_id

You need to understand, how JOIN works and its syntax.
select s.sponsor_name, count(*) as total_racer
from
racer r inner join sponsor s
on r.sponsor_id=s.sponsor_id
group by r.sponsor_id
You need to specify both tables in FROM clause, which you were missing.

You could use a join ( left join if not al the sponsor have racer ) and get the result without subselect using group by and count
select s.sponsor_name , count(*)
from SPONSOR s r
left JOIN racer r s.sponsor_id = r.sponsor_id
GROUP BY s.sponsor_name

Your version, with a subquery is reasonable, particularly because in MySQL it can have better performance than the corresponding GROUP BY query. However, it needs to be a correlated subquery. That looks like:
select s.*,
(select count(*)
from racer r
where s.sponsor_id = r.sponsor_id
) as cnt
from sponsor s;
In other words, choose either the JOIN method or the subquery method, but not both for the same value.

Related

Return the company with most film in a genre

I am working on this project at my university, where I need to create a query to the database. I want the query to return the company with most movies in the given genre. At the moment I have this query, but this only return one company, but there can probably be more than one.
SELECT CompanyID, CategoryID, COUNT(*) as NumberOfMovies
FROM Movie
NATURAL JOIN CategoryFilm
NATURAL JOIN Category
NATUAL JOIN Comapny
GROUP BY CategoryID, CompanyID
Order by NumberOfMovies DESC LIMIT 1
I beleave I will need a "having" in here.
pls try this, it may because you added limit 1, which only show 1st retrieved record
SELECT CompanyID, CategoryID, COUNT(*) as NumberOfMovies
FROM Movie
NATURAL JOIN CategoryFilm
NATURAL JOIN Category
NATURAL JOIN Comapny
GROUP BY CategoryID, CompanyID
Order by NumberOfMovies DESC
I assume by "category" you mean "genre" -- or that they are the same thing.
Do not use NATURAL JOIN. It does not even use properly declared foreign key relationships, instead relying merely on name similarity between tables. It is dangerous because the columns used are not specified and can introduce hard-to-debug errors. I often refer to it as an "abomination" because it does not take table declarations into account.
If you have a given category, then I would expect a WHERE clause:
SELECT CompanyID, COUNT(*) as NumberOfMovies
FROM Movie m JOIN
CategoryFilm cf
ON cf.movie_id = m.movie_id JOIN
Company c
ON c.company_id = m.company_id
WHERE cf.category_id = ?
GROUP BY CategoryID
ORDER BY NumberOfMovies DESC
LIMIT 1;
If you want to allow ties, you can use window function rank():
select *
from (
select
co.companyID,
ca.categoryID,
count(*) NumberOfMovies,
rank() over(partition by c.categoryID order by count(*) desc) rn
from movie m
inner join categoryFilm cf on cf.movieID = m.movieID
inner join category ca on ca.categoryID = cf.categoryID
inner join company co on co.companyID = m.companyID
group by co.companyID, ca.categoryID
) t
where rn = 1
order by ca.categoryID
This gives you the top company for each and every category, ties included. If you want to filter on a given category, you can just add a where clause to the inner query.
Side note: do not use natural joins: they are error-prone. I rewrote the query to use inner joins instead (I made a few assumptions on the relations).

mysql counts with group by to show all types per country include where no record is present as 0

I have the following mysql query and attempting to do group by country and type, however for all countries not all types are available but would still like to see all types for every country populated with 0.
select distinct
t1.Country,
t2.sectype,
count(t1.secid) AS SecID
from test.t2
left outer join test.t1 on test.t2.sectype= test.t1.sectype
group by t1.Country, t2.sectype;
t1 has country, sectype and secid fields and have created another table t2 which has all sectype's possible.
I get the following output:
https://i.stack.imgur.com/VAdyj.png
As you can see Germany only has 3 sectype's attached to that country but would like to see all sectype's like Canada - to be like the following output:
https://i.stack.imgur.com/ZC73H.png
Is this possible to do? Thanks
Consider a cross join of your distinct country and sectype tables. Then left join this all possible pairings to your actual data table. Finally, use a SUM condition over COUNT. Below uses table names that should be updated to your actual tables:
select cj.Country,
cj.sectype,
sum(d.secid IS NOT NULL) AS Count_SecID
from
(select n.country, s.sectype
from sectypes_table s
cross join countries_table n) cj
left outer join actual_data d
on d.sectype = cj.sectype AND d.country = cj.country
group by cj.Country,
cj.sectype;
To avoid the cross join should you have many distinct values, create such a table beforehand and replace subquery with this new table:
create table country_sectypes as (
select n.country, s.sectype
from sectypes_table s
cross join countries_table n
);
select cs.Country,
cs.sectype,
sum(d.secid IS NOT NULL) AS Count_SecID
from country_sectypes cs
left outer join actual_data d
on d.sectype = cs.sectype AND d.country = cs.country
group by cs.Country,
cs.sectype;
Rextester Demo (using actual_data for distinct country and sectype)

Count of full outer join in mySQL

I'm trying to display the total number of rows in a full outer join table. I have the following code, but mysql says there is an error with duplicate columns. The 2 tables, actors and directors, have the same columns as they are supposed to provide similar information in their respective categories.
SELECT COUNT(*) FROM
(SELECT * FROM directors LEFT OUTER JOIN actors
ON directors.name = actors.name
UNION
SELECT * FROM directors RIGHT OUTER JOIN actors
ON directors.name = actors.name) AS table1;
What can be done to fix the code so it will run properly? FYI, the code from within the parenthesis runs fine. The problem only arises once I put in the SELECT COUNT(*) clause.
Becuase there are two name columns one is from directors table, another is from actors table, and you select * that will let DB engine confuse which name did you want to get.
if you only want to count total number you can try this.
SELECT COUNT(*) FROM
(
SELECT directors.name FROM directors LEFT OUTER JOIN actors
ON directors.name = actors.name
UNION
SELECT directors.name FROM directors RIGHT OUTER JOIN actors
ON directors.name = actors.name
) table1;
NOTE
I would suggest use select clear the columns and avoid using select *
It might be better to change the right join portion non-redundant, and just add separate
counts.
Generic version:
SELECT (SELECT COUNT(*) FROM A LEFT JOIN B ON A.x = B.x)
+ (SELECT COUNT(*) FROM B LEFT JOIN A ON B.x = A.x WHERE A.x IS NULL)
AS outerJoinSize
;
Note: I changed the RIGHT JOIN to a LEFT JOIN and swapped the tables around; in my experience, RIGHT JOIN just tends to make queries a little harder to read (especially when multiple joins are involved).
An completely different alternative...
SELECT
( SELECT SUM(dc1.c * IFNULL(ac1.c, 1)) AS jc
FROM (SELECT name, COUNT(*) AS c FROM directors GROUP BY name) AS dc1
LEFT JOIN (SELECT name, COUNT(*) AS c FROM actors GROUP BY name) AS ac1
ON dc1.name = ac1.name)
+ (SELECT SUM(IF(dc2.name IS NULL, ac2.c, 0)) AS jc
FROM (SELECT name, COUNT(*) AS c FROM actors GROUP BY name) AS ac2
LEFT JOIN (SELECT name, COUNT(*) AS c FROM directors GROUP BY name) AS dc2
ON ac2.name = dc2.name)
...this one figures out how many matches based on the joining field (3 instances of "Bob" in directors and 2 in actors means 6 join results for that name).
I'm not sure what you are getting at with the full join. But the best way to implement it in MySQL uses two left joins and a union:
select count(*)
from ((select name from directors) union -- on purpose
(select name from actors)
) da left join
directors d
on da.name = d.name left join
actors a
on da.name = a.name;
If I had to guess, though, you just want the number of distinct names between the two tables. If so:
select count(*)
from ((select name from directors) union -- on purpose
(select name from actors)
) da

multiple count from multiple tables and also group by grade

i have table with student_uid,grade,test_name as columns i want to count how many got each grade..for this
SELECT a.grade,COUNT(a.grade) AS count1
FROM 2015_2016_x_english_grades AS a
where test_name='ut1_marks'
GROUP BY grade
for single table worked how to do it for more than one table
my query:
SELECT a.grade, COUNT(a.grade),b.grade,COUNT(b.grade)
FROM 2015_2016_x_english_grades a
INNER JOIN 2015_2016_x_hindi_grades b ON a.grade=b.grade
WHERE a.test_name = b.ut1_marks='ut1_marks'
GROUP BY a.grade,b.grade
what is wrong in this?
i also tried this
SELECT a.grade,COUNT(a.grade),(SELECT COUNT(b.grade)FROM 2015_2016_x_biology_grades b where b.test_name='ut1_marks' GROUP BY b.grade)as count1 FROM 2015_2016_x_biology_grades a where test_name='ut1_marks' GROUP BY a.grade
it says [Err] 1242 - Subquery returns more than 1 row
Do the counting in subqueries, and join the subqueries.
SELECT e.grade, english_count, hindi_count
FROM (SELECT grade, COUNT(*) AS english_count
FROM 2015_2016_x_english_grades
WHERE test_name = 'ut1_marks'
GROUP BY grade) AS e
JOIN (SELECT grade, COUNT(*) as hindi_count
FROM 2015_2016_x_hindi_grades
WHERE test_name = 'ut1_marks'
GROUP BY grade) AS h
ON e.grade = h.grade
Or if there's a unique key in each table, you can do:
SELECT e.grade, COUNT(DISTINCT e.id) AS english_count, COUNT(DISTINCT h.id) AS hindi_count
FROM 2015_2016_x_english_grades AS e
JOIN 2015_2016_x_hindi_grades AS h ON e.grade = h.grade AND e.test_name = h.test_name
WHERE e.test_name = 'ut1_marks'
GROUP BY e.grade
Note that both of these queries will only show a grade if it exists in both tables. To get grades that only exist in one table, you need a FULL OUTER JOIN, but MySQL doesn't have this operation. See
Full Outer Join in MySQL
for how to emulate them.

Inner Join across 3 tables with possible empty tables

Here I have 3 tables. I want to pull all people that attended either Game A, or Game B or both. Here is a Venn diagram of what I'd like to get:
I'd obviously like to have a unique list of people (no duplicates). I started out using two inner joins, but that only gives me the inside circle where all 3 tables intersect (which makes sense).
So, what JOIN or combination should I use to pull this data?
Person
id
first
last
GameA
typeid
checkin_time
person_id
GameB
typeid
checkin_time
person_id
QUERY:
This is what I have tried, which only returns people that have attended BOTH Game A and Game B:
SELECT * FROM Person
INNER JOIN GameA ON Person.id = GameA.person_id
INNER JOIN GameB ON Person.id = GameB.person_id
I am able to get the results desired using this query as well, but I'm not sure if there is a better way to accomplish this:
SELECT * FROM Person, GameA, GameB
WHERE Person.id = GameA.person_id OR Person.id = GameB.person_id
GROUP BY Person.id
There are a few ways you could do this. One would be to make a UNION subquery returning only the person_id from both GameA and GameB then perform an INNER JOIN to limit Person to those only, or use an IN()` subquery:
SELECT
DISTINCT Person.*
FROM
Person
INNER JOIN (
SELECT person_id FROM GameA
UNION
SELECT person_id FROM GameB
) attendees ON Person.id = attendees.person_id
Alternatively, an IN() subquery:
SELECT
DISTINCT Person.*
FROM Person
WHERE id IN (
SELECT person_id FROM GameA
UNION
SELECT person_id FROM GameB
)
It might be faster than either of those though, to do the UNION on the outside. If you have FOREIGN KEY relationships defined where necessary, therefore enforcing indexing, you could do the INNER JOIN twice and then UNION the results of those:
SELECT p.*
FROM Person p INNER JOIN GameA ON p.id = GameA.person_id
UNION
SELECT p.*
FROM Person p INNER JOIN GameB ON p.id = GameB.person_id