How do I count in a left join query - mysql

How do I count the number of participants in the event_participants table. This is my table
event_place
id | name
1 | New York
2 | Canada
event_participants
id | event_place_id | name
1 | 1 | Jon
2 | 1 | Mike
3 | 2 | Van
and I am getting a wrong result on my query
SELECT count(*) as count
FROM event_participants as t1
LEFT JOIN event_place as t2
ON t1.event_place_id = t2.id;
and the result is 3
I should be getting a result like this
New York | 2
Canada | 1

your query like this.
select pl.id,pl.name,count(*) from
event_place pl
left join event_participants ep
on pl.id = ep.event_place_id
group by pl.id;

You are getting correct results because you are counting all the records.
If you want the counts per event place, you should GROUP BY event place
SELECT t1.event_place_id, t2.name, count(*) as count
FROM event_participants as t1
LEFT JOIN event_place as t2
ON t1.event_place_id = t2.id
GROUP BY t1.event_place_id, t2.name,;

select a.name, count(1) from event_place a, event_participants b
where b.event_place_id = a.id
group by a.name;

There appear to be a couple of issues.
I presume you want a list of all the even places, and the number of people at each one. If so that suggests that you need to LEFT OUTER JOIN the event_participants table to the event_place table, rather than the other way round. This way you can have places listed which have no participants.
You also need a GROUP BY clause.
And if you use COUNT(*) you are counting the returned rows (prior to the grouping). However if there is no matching participants then a row is still returned for the place, hence you would get 1 as the count. To avoid this specify a column in the COUNT() which is on the participants table. COUNT with a column name counts the number of non NULL values of that column, hence if no participants it will return 0 for that place:-
SELECT t2.name,
COUNT(t1.id) AS count
FROM event_place t2
LEFT JOIN event_participants t1
ON t1.event_place_id = t2.id
GROUP BY t2.name

Related

Not sure how to get this working with respect a SQL query

I have two tables named table1 and table2:
Table1
id date email cId
1 2013-08-28 12:21:39 t#gmail.com 12345
2 2013-07-27 10:15:18 k#gmail.com 12345
3 2018-02-13 09:41:43 a#gmail.com 12345
4 2018-02-02 10:14:42 n#gmail.com 45678
5 2017-11-16 10:16:51 l#gmail.com 45678
Table2
id status
12345 1
45678 1
56789 0
When I execute a query I am expecting to get row from table1 which has max date.
select c.id 'table 2 Id'
, DATE_FORMAT(Max(u.date),'%Y-%m-%dT%TZ') 'Date'
, u.email 'User'
from table2 c
LEFT
JOIN table1 u
ON u.cId = c.id
where c.status = 1
group
by c.id
order
by c.id;
How ever what I see is kind of confusing.
table 2 Id Date USER
12345 2018-02-13 09:41:43 t#gmail.com
I am expecting the output to be
table 2 Id Date USER
12345 2018-02-13 09:41:43 a#gmail.com
Because the max date that is selected is not same of the user t#gmail.com but of a#gmail.com
Any suggestions on where has it gone wrong and how can I tweak it to get correct result?
The moment you use a grouping function (i.e. max, sum, count, etc.) you must specify only segregating columns in the SELECT clause.
In your case, there are several emails for one given id, much like the date field.
You can't just specify
SELECT id, max(date), email ...
it wouldn't make sense, because you need to specify a grouping function for the mail.
What you're really interested in, is "the email that corresponds to the row whose date is max(date) for a given id".
This must be done using a subquery. Something like this:
SELECT
tmax.cid,
tmax.maxdate,
table1.email,
table2.status
FROM
table2
INNER JOIN table1
ON table1.cid = table2.id
INNER JOIN (
SELECT
cid,
max(date) AS maxdate
FROM
table1
GROUP BY
cid
) AS tmax
ON tmax.cid = table1.cid AND tmax.maxdate = table1.date;
The above query executed on your data set, will give this exact output (2 rows):
cid maxdate email status
12345 2018-02-13 09:41:43 a#gmail.com 1
45678 2018-02-02 10:14:42 n#gmail.com 1
which means, in English: "For each id in table2, bring its status, and bring the line in table1 for the corresponding cid, and whose date is the max date for same cid within table1."
Because I used INNER JOINs, the records in table1 that mention a cid that does not exist in table2, are discarded.
You could write the query like this (add an order desc on u.date):
SELECT c.id 'table 2 Id', DATE_FORMAT(MAX(u.date),'%Y-%m-%dT%TZ') 'Date', u.email 'User'
FROM table2 c
LEFT JOIN table1 u ON u.cId = c.id
WHERE c.status = 1
GROUP BY c.id
ORDER BY c.id, u.date DESC;

How to join two tables, with distinct columns on either side?

I have two tables I'm trying to join to produce a unique set of data for a third table, but having trouble doing this properly.
The left table has an id field, as well as a common join field (a).
The right table has the common join field (a), and another distinct field (b)
I'm trying to extract a result-set of id and b, where neither id nor b are duplicated.
I have an SQL fiddle set up: http://www.sqlfiddle.com/#!9/208de/3/0
The ideal results should be:
id | b
---+---
1 | 1
2 | 2
3 | 3
Each id and b value appears only once (it's only coincidence they match here, that can't be assumed always).
Thanks
What about a CTE along with a DISTINCT, Would that work?
WITH
cte1 (ID, B)
AS
(
SELECT DISTINCT Table1.ID
FROM Table1
WHERE Table1.ID IS NOT NULL
GROUP BY Table1.ID
)
SELECT DISTINCT
Table2.b
FROM Table2 AS sp
INNER JOIN cte1 AS ts
ON sp.b <> ts.ID
ORDER BY ts.ID DESC

Select all rows that have same ID

I have this table:
ID | Part
1 | A
1 | B
1 | C
2 | B
2 | C
3 | A
3 | D
3 | E
4 | B
4 | D
and want a query that will grab all ID's that have an A, and return a list of all other parts with that ID.
e.g: Want Parts related to B:
Part | Count
A | 1
C | 2
D | 1
What I have currently:
SELECT * FROM tble WHERE ID IN (SELECT DISTINCT ID FROM tble t WHERE Part = ?)
GROUP BY Part ORDER BY COUNT(Part) DESC
This works, but is quite slow and I'm looking to improve it, but having difficulty
Your query is not unreasonable, although the distinct is unnecessary and I would use exists rather than in. And, the outer select needs to be fixed for the aggregation
SELECT t.part, COUNT(*)
FROM tble t
WHERE EXISTS (SELECT 1 FROM tble t2 WHERE t2.ID = t.ID AND t2.Part = ?)
GROUP BY t.Part
ORDER BY COUNT(*) DESC;
Then, to optimize this query, you want an index:
create index idx_tble_id_part on tble(id, part);
Simplify this.. Once you have the logic down, then add back in the SELECT * FROM..
SELECT Part, COUNT(Part) As Count_of_Part
GROUP BY Part ORDER BY COUNT(Part) DESC
Do a join from the table back to itself on ID, and then count the distinct values that pop up:
SELECT b.part, COUNT(DISTINCT b.id)
FROM
table as a
INNER JOIN table as b ON
a.id = b.id AND
a.part <> b.part
WHERE
a.part = 'B'
GROUP BY b.part
This can be simply done by joining back to the table:
SELECT t1.part
,count(*)
FROM tble t1
INNER JOIN tble t ON t.id = t1.id
AND t.part = 'B'
AND t1.part <> t.part
GROUP BY t1.part
SQL Fiddle Demo
You should be able to do this by grouping the data.
Try something like this:
SELECT part, COUNT(id) AS TotalCountId
FROM TABLE_NAME
GROUP BY ID

SQL Left Join using COUNT

My query is so close, i've gone through almost all the other times this has been posted, but I'm not quite there.
SELECT a.name, IFNULL(b.student_id, 0) AS count
FROM student AS a
LEFT JOIN (SELECT student_id, COUNT(*) as count FROM quizactivity GROUP BY student_id)
AS b
ON a.id = b.student_id;
This returns a table with the names of the four entries, and then their actual id on their own table, a.id.
Name | Count
Will 1
Jane 2
Sally 0
Dave 4
Sally returns 0 because she has no results.
I am cleary returning the id of the table instead of the counts - where am I wrong?
Don't you want the count?
SELECT a.name, COALESCE(b.count, 0) AS count
FROM student a LEFT JOIN
(SELECT student_id, COUNT(*) as count
FROM quizactivity
GROUP BY student_id
) b
ON a.id = b.student_id;

COUNT function with INNER JOIN

I have the following table:
A FromA User
1 NULL Bob
2 1 Bob
3 1 Chris
4 2 Chris
User is the name of the person who created item A. FromA is the source that the User grabbed it from.
I want to figure out is Chris' most frequency source.
My query
SELECT count(T1.A GROUP BY T1.User), T1.User
FROM Table T0
INNER JOIN Table T1 ON T0.FromA=T1.A
WHERE T0.User='Chris'
It should return Bob=2. But it doesn't seem to work.
Try this:
select t2.user, count(*) Total from t t1
join t t2 on t1.fromA = t2.a
where t1.user = 'Chris'
group by t2.user
order by Total desc
limit 1
The limit 1 will give you just the most frequently used source.
Edit:
inner join will fail to fetch record=>1 | NULL | Bob as 'fromA' column has null value. so, switch to left join – Angelin Nadar
Nope. Here is a working example
You just have your group by in the wrong place. This should work
SELECT count(T1.A ), T1.User
FROM Table T0
INNER JOIN Table T1 ON T0.FromA=T1.A
WHERE T0.User='Chris'
GROUP BY T1.User
Try with this, I have changed table aliases:
SELECT count(*), t_User.User
FROM
Table t_FromA
LEFT OUTER JOIN
Table t_User
ON t_User.FromA=t_FromA.A
WHERE t_FromA.User='Chris'