How to select table and count other table - mysql

Suppose I have two tables:
Customers
Name | id |
-------------------
Benny | 1 |
Wilson | 2 |
Joe | 3 |
Austin | 4 |
Orders
Product | id |
---------------------
TV | 1 |
Hifi-set | 1 |
HTPC | 1 |
CD | 1 |
DVD | 1 |
CD | 1 |
DVD | 1 |
And this is what I want with the results:
Name | Orders |
-------------------
Benny | 7 |
Wilson | 0 |
Joe | 0 |
Austin | 0 |
I'm not familiar with SQL, But I tried:
SELECT c.Name FROM Customers AS c LEFT JOIN Orders AS o ON c.id=o.id GROUP BY c.Name
But got a wrong result:
Name | Orders |
-------------------
Benny | 4 |
Wilson | 1 |
Joe | 1 |
Austin | 1 |
What do I do?

Try:
select
c.Name,
(select count(1) from Orders where ID=c.ID)
from
Customers as c

By not using SubQuery, you can also JOIN instead.
SELECT a.Name, COUNT(b.id)
FROM Customers a LEFT JOIN Orders b
on a.ID = b.ID
GROUP BY a.Name

Related

MySQL query to count occurrences from multiple tables

I have a problem when I have to select everything from one table (persons) then count how many objects they own by counting their occurrences on other tables (pens, chairs, books)
The current data is as followed:
select * from persons;
+----+-------+
| id | name |
+----+-------+
| 1 | Alex |
| 2 | Brad |
| 3 | Cathy |
+----+-------+
select * from pens;
+----+-----------+
| id | person_id |
+----+-----------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
| 4 | 3 |
+----+-----------+
select * from chairs;
+----+-----------+
| id | person_id |
+----+-----------+
| 1 | 1 |
+----+-----------+
select * from books;
+----+-----------+
| id | person_id |
+----+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+-----------+
I want the result to be something like this
+----+-------+-----------------------+-------------------------+------------------------+
| id | name | count(pens.person_id) | count(chairs.person_id) | count(books.person_id) |
+----+-------+-----------------------+-------------------------+------------------------+
| 1 | Alex | 0 | 1 | 1 |
| 2 | Brad | 3 | 0 | 1 |
| 3 | Cathy | 1 | 0 | 1 |
+----+-------+-----------------------+-------------------------+------------------------+
I have tried using inner join and left outer join, but join gave me an empty set (since no person matches all of the objects) and left outer join gave me incorrect results:
> select persons.*, count(pens.person_id),count(chairs.person_id),count(books.person_id) from persons join pens on pens.person_id=persons.id join books on books.person_id=persons.id join chairs on chairs.person_id=persons.id group by persons.id;
Empty set (0.002 sec)
> select persons.*, count(pens.person_id),count(chairs.person_id),count(books.person_id) from persons left outer join pens on pens.person_id=persons.id left outer join books on books.person_id=persons.id left outer join chairs on chairs.person_id=persons.id group by persons.id;
# +----+-------+-----------------------+-------------------------+------------------------+
id | name | count(pens.person_id) | count(chairs.person_id) | count(books.person_id) |
# +----+-------+-----------------------+-------------------------+------------------------+
1 | Alex | 0 | 1 | 1 |
2 | Brad | 3 | 0 | 3 |
3 | Cathy | 1 | 0 | 1 |
# +----+-------+-----------------------+-------------------------+------------------------+
Any suggestions will be greatly appreciated, sorry if it's obvious, I'm fairly new at this.
Using a left join approach to subqueries on each table we can try:
SELECT
p.id,
p.name,
COALESCE(ps.cnt, 0) AS cnt_pens,
COALESCE(c.cnt, 0) AS cnt_chairs,
COALESCE(b.cnt, 0) AS cnt_books
FROM persons p
LEFT JOIN
(
SELECT person_id, COUNT(*) AS cnt
FROM pens
GROUP BY person_id
) ps
ON ps.person_id = p.id
LEFT JOIN
(
SELECT person_id, COUNT(*) AS cnt
FROM chairs
GROUP BY person_id
) c
ON c.person_id = p.id
LEFT JOIN
(
SELECT person_id, COUNT(*) AS cnt
FROM books
GROUP BY person_id
) b
ON b.person_id = p.id
ORDER BY
p.id;

GROUP by version and display by row

+----------+--------+
| name | version|
+----------+--------+
| book | 2 |
| book | 1 |
| book | 1 |
| pen | 1 |
| pen | 2 |
| pen | 2 |
| pen | 2 |
| paper | 1 |
+----------+--------+
I have the table above and i want to make a query to group by name and count by version(row)
Result:
+----------+--------+--------+
| name | version| count |
+----------+--------+--------+
| book | 1 | 2 |
| book | 2 | 1 |
| pen | 1 | 1 |
| pen | 2 | 3 |
| paper | 1 | 1 |
| paper | 2 | 0 |
+----------+--------+--------+
The query would be
SELECT name, version, count(*) as count
FROM your_table_name
GROUP BY name, version
If you want all name/version combinations, then use a cross join to generate all rows and then left join to bring in the existing data:
select n.name, v.version, count(t.name)
from (select distinct name from t) n cross join
(select distinct version from t) v left join
t
on t.name = n.name and t.version = v.version
group by n.name, v.version
order by n.name, v.version;

Count the number of students and display in another table

I have Student and Course Table:
Student(Roll_no(primary), Name, Course_id(foreign))
Course(Course_no(primary), Course_name)
How will I retrieve:
a. The table with the details of Courses in which more than 2 students got admitted.
b. The Course table along with a count column.
What I tried for the first problem:
SELECT * FROM Course WHERE(SELECT COUNT(*) FROM Student GROUP BY Course_no WHERE COUNT(*) > 2);
I'm not sure what I did, but that didn't work. I am new to Database System
.
Sample:
Student Table
+---------+----------+----------+-----------+
| Roll_no | Name | Semester | Course_no |
+---------+----------+----------+-----------+
| 1 | a | 3 | 101 |
| 2 | b | 5 | 101 |
| 3 | c | 3 | 101 |
| 4 | c | 3 | 101 |
| 5 | d | 3 | 101 |
| 7 | b | 4 | 102 |
+---------+----------+----------+-----------+
Course Table
+-----------+-------------+
| Course_no | Course_name |
+-----------+-------------+
| 101 | BCA |
| 102 | BSC |
+-----------+-------------+
For the First Part I expect a table like:
+-----------+-------------+
| Course_no | Course_name |
+-----------+-------------+
| 101 | BCA |
+-----------+-------------+
For the Second part I expect a table like
+-----------+----------------------+
| Course_no | Course_name |Total |
+-----------+-------------+--------+
| 101 | BCA |5 |
| 102 | BSC |1 |
+-----------+-------------+--------+
First Part:
You need to use JOIN and HAVING
SELECT c.Course_no,c.Course_name
FROM Course c
INNER JOIN Student s on c.Course_no = s.Course_id
GROUP BY c.Course_no,c.Course_name
HAVING count(1) > 2
sqlfiddle:http://sqlfiddle.com/#!9/387386/3
Second part:
You need to JOIN and GROUP BY COUNT
SELECT c.Course_no,c.Course_name,count(1) 'totle'
FROM Course c
INNER JOIN Student s on c.Course_no = s.Course_id
GROUP BY c.Course_no,c.Course_name
sqlfiddle:http://sqlfiddle.com/#!9/bad7e3/1

MySQL Count Comma Delimited

I have 3 tables like this:
table_events
+------+----------+----------------------+
| ID | Title | Employees |
+------+----------+----------------------+
| 1 | Event1 | john,james |
+------+----------+----------------------+
| 2 | Event2 | sarah,jessica |
+------+----------+----------------------+
table_check_in
+------+----------+----------+---------------------+
| ID | Time | EventID | By |
+------+----------+----------+---------------------+
| 1 | 08:30 | 1 | john |
+------+----------+----------+---------------------+
| 2 | 08:30 | 1 | james |
+------+----------+----------+---------------------+
| 3 | 09:30 | 1 | john |
+------+----------+----------+---------------------+
| 4 | 10:30 | 2 | sarah |
+------+----------+----------+---------------------+
| 5 | 10:35 | 2 | sarah |
+------+----------+----------+---------------------+
table_problems
+------+----------------+----------+---------------------+
| ID | Comment | EventID | By |
+------+----------------+----------+---------------------+
| 1 | Broken door | 1 | john |
+------+----------------+----------+---------------------+
| 2 | Slippery floor | 1 | john |
+------+----------------+----------+---------------------+
| 3 | Leaking tap | 1 | john |
+------+----------------+----------+---------------------+
| 4 | Broken window | 2 | jessica |
+------+----------------+----------+---------------------+
| 5 | Broken glass | 2 | jessica |
+------+----------------+----------+---------------------+
I would like to print something like this:
+------+----------+---------------+-------------------+-------------------+
| ID | Title | Employees | Count_Check_In | Count_Problems |
+------+----------+---------------+-------------------+-------------------+
| 1 | Event1 | john,james | john:2,james:1 | john:3,james:0 |
+------+----------+---------------+-------------------+-------------------+
| 2 | Event2 | sarah,jessica | sarah:2,jessica:0 | sarah:0,jessica:2 |
+------+----------+---------------+-------------------+-------------------+
I know this problem would be trivial if the database was designed properly, but we don't have the luxury of an application rewrite at the moment.
You need to initially get all the employees for each event id from check in and problem tables by using a union.
Then left join the counts from each of check in and problems table to the previous result to get the 0 counts as well.
Finally use a group_concat to get the result in one row for each event id.
select te.id,te.title,te.employees
,group_concat(concat(t.`By`,':',coalesce(tccnt.cnt,0))) count_check_in
,group_concat(concat(t.`By`,':',coalesce(tpcnt.cnt,0))) count_problems
from table_events te
left join (select eventid,`By` from table_check_in
union
select eventid,`By`from table_problems) t on te.id = t.eventid
left join (select eventid,`By`,count(*) cnt from table_check_in group by eventid,`By`) tccnt on tccnt.eventid = t.eventid and tccnt.`By`=t.`By`
left join (select eventid,`By`,count(*) cnt from table_problems group by eventid,`By`) tpcnt on tpcnt.eventid = t.eventid and tpcnt.`By`=t.`By`
group by te.id,te.title,te.employees
Sample Demo (thanks to #valex for setting up the schema)
You can use GROUP_CONCAT to get a result. Here is an example. The only thing missed is employees with 0 check ins or problems.
SELECT ID, Title,Employees,
GROUP_CONCAT(DISTINCT CONCAT(check_in.`By`,':',check_in.cnt))
as Count_Check_In,
GROUP_CONCAT(DISTINCT CONCAT(problems.`By`,':',problems.cnt))
as Count_Problems
FROM table_events
LEFT JOIN (SELECT EventID,`By`, COUNT(*) as cnt
FROM table_check_in
GROUP BY EventID,`By`) as check_in
ON table_events.ID = check_in.EventID
LEFT JOIN (SELECT EventID,`By`, COUNT(*) as cnt
FROM table_problems
GROUP BY EventID,`By`) as problems
ON table_events.ID = problems.EventID
GROUP BY table_events.id
Demo

Multiple Select Join query with corresponding column on one table to others

Lets say that I have something table like this:
<b>Name</b>
+---------+--------+
| name_id | name |
+---------+--------+
| 5 | Betti |
| 6 | Derry |
| 7 | Alfred |
| 8 | Elsie |
| 9 | Cinta |
+---------+--------+
<b>Goods</b>
+----------+-----------+
| goods_id | goods |
+----------+-----------+
| 1 | Computer |
| 2 | AC |
| 3 | Microwave |
| 4 | TV |
+----------+-----------+
<b>Transaction</b>
+-------+---------+----------+
| ai_id | name_id | goods_id |
+-------+---------+----------+
| 1 | 7 | 2 |
| 2 | 5 | 4 |
| 3 | 9 | 3 |
+-------+---------+----------+
I want to replace name_id column on Transaction table with name column on Name table with corresponding name_id column and so for goods_id to produce something similar to this table:
<b>Transaction</b>
+-------+--------+-----------+
| ai_id | name | goods |
+-------+--------+-----------+
| 1 | Alfred | AC |
| 2 | Betti | TV |
| 3 | Cinta | Microwave |
+-------+--------+-----------+
If you're looking to just display the information rather than actually "replacing" your tables with new ones, then you could use a SELECT query with a simple INNER JOIN. This way you can display columns from multiple tables.
SELECT T.ai_id, N.Name, G.goods
FROM Transaction T
INNER JOIN Name N ON N.name_id = T.name_id
INNER JOIN Goods G ON G.goods_id = T.goods_id;
Try with inner join
SELECT T.ai_id,N.name,G.goods
FROM Transaction as T
INNER JOIN Goods as G ON T.goods_id = G.goods_id
INNER JOIN Name as N ON N.name_id = T.name_id;
Try this one
select tb3.ai_id,tb2.name,tb1.goods from Goods tb1,Name tb2,Transaction tb3 where tb3.name_id=tb2.name_id and tb3.goods_id=tb1.goods_id order by tb3.ai_id
try this:
SELECT C.ai_id,A.name,B.goods
FROM Transaction C
INNER JOIN Name A
ON A.name_id=C.name_id
INNER JOIN Goods B
ON B.goods_id=C.goods_id;
http://sqlfiddle.com/#!2/3c5f3/8