SQL Left Join using COUNT - mysql

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;

Related

Merge two tables with same columns and get the column value in specific table

I have two tables that have the same column of position and salary.
Table_a
ID
Name
Position
Salary
1
Peter
Sale
10,000
2
Tom
IT
15,000
3
Jane
Sale
12,000
4
Mary
PR
8,000
5
John
IT
14,000
Table_b
ID
Position
Salary
1
Driver
9,000
2
Manager
20,000
4
Sale
13,000
I would like to merge two tables that the output is based on the Position value and Salary value of Table_b.
Output
ID
Name
Position
Salary
1
Peter
Driver
9,000
2
Tom
Manager
20,000
3
Jane
Sale
12,000
4
Mary
Sale
13,000
5
John
IT
14,000
Please give me an advice how can I query and get the above output.
SELECT id,
t1.name,
COALESCE(t2.position, t1.position),
COALESCE(t2.salary, t1.salary)
FROM table_a t1
LEFT JOIN table_b t2 USING (id)
Some rows in table_a don't have a matching row in table_b. Any rows in table_b that don't have a matching row in table_a will be ignored. We assume that ID is unique in each table (meaning for example there won't be two rows in table_b with the same ID value). We will match the rows on ID value.
We can make table_a the driving table in an outer join to table_b. Let's first get that working, returning all the columns from both tables, and verify the return is what we expect.
SELECT a.ID
, a.Name
, a.Position
, a.Salary
, b.ID AS b_ID
, b.Position AS b_position
, b.Salary AS b_salary
FROM table_a a
LEFT
JOIN table_b b
ON b.ID = a.ID
ORDER
BY a.ID
We see that in the result from the first query, on rows where we didn't get a matching row from table_b, column b_ID (and all the columns from table_b) are NULL.
We can add some expressions in the SELECT list to get the Salary from table_b where we found a matching row, or otherwise return Salary from table_a where we didn't.
There's lots of possible expressions to do that, but they all key on the idea that when we don't have a matching row from the outer joined table, the values in those columns will be NULL.
So the trick is test whether we found a matching row from table_b (or if we did get a matching row in table_b, the row had a NULL value for Salary)
Adding some example expressions to check if b.ID or b.Salary is NULL.
SELECT a.Name
, a.Position
, a.Salary
, b.ID AS b_ID
, b.Position AS b_position
, b.Salary AS b_salary
, CASE WHEN b.ID IS NULL THEN a.Salary ELSE b.Salary END AS _Salary_x1
, IFNULL(b.Salary,a.Salary) AS _Salary_x2
, IF(b.Salary IS NULL,a.Salary,b.Salary) AS _Salary_x3
FROM table_a a
LEFT
JOIN table_b b
ON b.ID = a.ID
ORDER
BY a.ID

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 do I count in a left join query

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

sql - select rows with a distinct value in a specific column

Let's assume that I have the following table:
id player_name team
1 Gladiator A
2 DarkLord B
3 Alligator A
4 MonaLisa C
5 SpongBob C
6 Mikasa B
I want to select one player from each team, which means that all the selected rows must have a unique value in the 'team' column. How can I accomplish this in MySQL?
In my example the selected rows should be:
id player_name team
1 Gladiator A
2 DarkLord B
4 MonaLisa C
This is one way to do it using a derived table so you select one id per team and join it to the original table.
select t.id, t.player_name, t.team
from tablename t
join (select team, min(id) as minid from tablename group by team) x
on x.team = t.team and x.minid = t.id
One simple way would be to fetch using a group by criteria. (Assuming your table name is TEAM_TABLE)
SELECT * FROM TEAM_TABLE GROUP BY TEAM;
This would return the first record occurring for each value of the team column.

Get duplicate rows and count based on single column

I need to get the distinct rows based on a single column (code in this case) where there are duplicates of that column value. Along with other information from the row and the number of duplicate rows there are. for example:
ID code ownerName
--------------------------
1 001 Mr. Brown
2 001 Mr. Pink
3 002 Mr. White
4 003 Mr. Blonde
I need this query to return
ID code ownerName count
----------------------------------
1 001 Mr. Brown 2
the duplicate row information does not matter which gets returned, but I'm having trouble combining the distinct codes with the count column.
I've tried a query like this:
SELECT DISTINCT A.code, A.ownerName
FROM Customers A WHERE
EXISTS( SELECT * FROM Customers WHERE code = A.code AND id <> A.id)
order by A.code;
but I'm having trouble getting the count; and with this query
SELECT code, COUNT(*) as numberDuplicates
FROM Customers GROUP BY code HAVING COUNT(*) > 1
I'm having trouble getting other information I don't want to group by. Can anyone help me figure out how to structure the correct query?
If I understand what you are looking for, this should work:
This will select all entries with a non-unique code and return the number of records using that code.
SELECT DISTINCT A.ID, A.Code, A.ownerName, B.Count
FROM Customers A
JOIN (
SELECT COUNT(*) as Count, B.Code
FROM Customers B
GROUP BY B.Code
) AS B ON A.Code = B.Code
WHERE B.Count > 1
ORDER by A.Code;
I think you can try something like below
SELECT TOP 1 C.ID, C.Code, C.OwnerName, C1.NumberDuplicates
FROM
Customers C
INNER JOIN
(
SELECT Code, COUNT(*) as NumberDuplicates FROM Customers GROUP BY code HAVING COUNT(*) > 1
) C1
ON C.Code = C1.Code
Hope this Helps!!
SELECT COUNT(DISTINCT CustomerID) AS NumberOfCustomers FROM Orders;