Count of full outer join in mySQL - 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

Related

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)

MySQL - join two tables, group and count

I have two tables:
reviewStatusPhases - id|name
and
userPhase - id|reviewStatusPhase_id|user_id|created_at|updated_at
The reviewStatusPhases table have records inserted (Active, Inactive, On Pause, Terminated...), and userPhase is empty.
The tables are connected via
userPhase.reviewStatusPhase_id = reviewStatusPhases.id
one to one.
Is it possible that in one query I get all reviewStatusPhases, and cound how many users are in each phase? In this case I will get something like this:
Active (0 Users)
Inactive (0 Users)
On Pause (0 Users)
Terminated (0 Users)
I'm making some assumptions here (e.g. INNER JOIN versus LEFT JOIN in the join, and DISTINCT in the count), but it sounds like you just want
SELECT reviewStatusPhases.name, COUNT(DISTINCT userPhase.user_id)
FROM userPhase INNER JOIN reviewStatusPhases
ON userPhase.reviewStatusPhase_id = reviewStatusPhases.id
GROUP BY reviewStatusPhases.name
Query will be as follows:
SELECT r.name as `name`, count(u.id) as `count` FROM reviewStatusPhases r LEFT OUTER JOIN userPhase u ON r.id = u.reviewStatusPhase_id GROUP BY r.name
left outer join with reviewStatusPhases on left to show all names.
group by names of reviewStatusPhases.
display reviewStatusPhases name and count of user id's (to neglect null values)
Use LEFT JOIN as follows:
SELECT COUNT(m.UserId) FROM Table1 m
LEFT JOIN Table2 k ON k.StatusId = m.StatusId
WHERE k.Status = 'Inactive'
You can easily use the Status column to track the users and their activities. In your case, ReviewStatus.
I hope the following will be helpful
SELECT RPS.Name, COUNT(UP.user_id)
FROM reviewStatusPhases RPS
LEFT OUTER JOIN userphases UP ON RPS.id = UP.reviewStatusPhase_id
GROUP BY RPS.Name
ORDER BY RPS.Name
SELECT
DISTINCT s.s_level AS 'Level',
COUNT(DISTINCT s.s_id) AS Schools,
COUNT(DISTINCT st.st_id) AS Teachers
FROM schools AS s
JOIN school_teachers AS st ON st.st_school_idFk = s.s_id AND st.st_status = 1
WHERE s.s_status = 1
GROUP BY s.s_level

Find Count of racers from Race Table

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.

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

Left outer join to a generated table?

Am I on completely the wrong tack ?
I want to do a left outer join to a query generated from 2 tables , but i keep getting errors. Do I need a different approach?
t1:
ID, Surname,Firstname
t2:
ID,JobNo,Confirmed
I have the following query:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
I want to add:
LEFT OUTER JOIN contacted (ON t1.StaffID=contact.ID AND t2.JobNo=contact.JobNo)"
Can I do a left outer join to a query generated from 2 tables ?
In order to use the t1 and t2 in the left outer join that you want to add you need to join them with the first tables, you can't reference them directly in the left outer join you, Something like the following:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
Inner join t1 on ...
Inner join t2 on ...
LEFT OUTER JOIN contacted c
on t1.StaffID=c.ID AND t2.JobNo = c.JobNo
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
So, based in your tables' structure, define the conditions of the two joins with t1 and t2 with other tables.
Here is the an example of a left join to a sub query. This might be what you are looking for.
select
parts.id,
min(inv2.id) as nextFIFOitemid
from test.parts
left join
( select
inventory.id,
coalesce(parts.id, 1) as partid
from test.inventory
left join test.parts
on (parts.id = inventory.partid)
) inv2
on (parts.id = inv2.partid)
group by parts.id;