SQL search merge - mysql

I'm trying to merge two select sentence. Is it possible ?
I have three tables :
score
+------+---------+-------+
| ID | SUBJECT | SCORE |
+------+---------+-------+
| 1 | Chinese | 65 |
| 1 | English | 75 |
| 2 | Chinese | 60 |
| 2 | English | 70 |
| 3 | Chinese | 80 |
| 3 | English | 50 |
+------+---------+-------+
student
+------+----------+--------+
| ID | CLASS_ID | NAME |
+------+----------+--------+
| 1 | 1 | TOM |
| 2 | 1 | ANNA |
| 3 | 2 | JOHN |
+------+----------+--------+
class
+------+----------+
| ID | NAME |
+------+----------+
| 1 | 5th |
| 2 | 6th |
+------+----------+
mysql> select class.NAME as CLASS_NAME, student.NAME from class inner join student on student.CLASS_ID = class.ID;
+------------+--------+
| CLASS_NAME | NAME |
+------------+--------+
| 5th | TOM |
| 6th | ANNA |
| 6th | JOHN |
+------------+--------+
mysql> select SUM(SCORE) as total from score group by ID;
+-------+
| total |
+-------+
| 140 |
| 130 |
| 130 |
+-------+
Could I merge two select sentence let it be
+------------+--------+-------+
| CLASS_NAME | NAME | total |
+------------+--------+-------+
| 5th | TOM | 140 |
| 6th | ANNA | 130 |
| 6th | JOHN | 130 |
+------------+--------+-------+
Or is there any better search sentence to do this well?
I try use two sentence to merge , but can't have a good idea.
mysql> select class.NAME as CLASS_NAME, student.NAME from class inner join student on student.CLASS_ID = class.ID;
mysql> select SUM(SCORE) as total from score group by ID;
hope it can be merge success or have another answer to do this well.

You can use inner join to merge the second query. Below query takes in consideration that the join condition will be score.id with student.id
select c.name as class_name,
st.name ,
sc.total
from class c
inner join student st on st.class_id = c.id
inner join ( select id,
SUM(SCORE) as total
from score
group by id
) as sc on sc.id=st.id ;
https://dbfiddle.uk/tauTGBFO

Related

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;

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

MySQL Limit Results Based on Join Table

I have 2 tables,but linked in many to many relations so 3 tables :
Table Author :
idAuthor,
Name
+----------+-------+
| idAuthor | Name |
+----------+-------+
| 1 | Renee |
| 2 | John |
| 3 | Bob |
| 4 | Bryan |
+----------+-------+
Table Publication:
idPublication,
Title,
Type,
Date,
Journal,
Conference
+---------------+--------------+------+-------------+------------+-----------+
| idPublication | Title | Date | Type | Conference | Journal |
+---------------+--------------+------+-------------+------------+-----------+
| 1 | Flower thing | 2008 | book | NULL | NULL |
| 2 | Bees | 2009 | article | NULL | Le Monde |
| 3 | Wasps | 2010 | inproceding | KDD | NULL |
| 4 | Whales | 2010 | inproceding | DPC | NULL |
| 5 | Lyon | 2011 | article | NULL | Le Figaro |
| 6 | Plants | 2012 | book | NULL | NULL |
+---------------+--------------+------+-------------+------------+-----------+
Table author_has_publication :
Author_idAuthor,
Publication_idPublication
+-----------------+---------------------------+
| Author_idAuthor | Publication_idPublication |
+-----------------+---------------------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 3 | 6 |
+-----------------+---------------------------+
What I want to do is get the top X author having the most publications.
I achieved to get the result avec the idAuthor having the most publications, using this request :
SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC;
I get the list of the authors id, ordered by the number of publications :
+-----------------+-------+
| Author_idAuthor | count |
+-----------------+-------+
| 3 | 3 |
| 2 | 2 |
| 1 | 2 |
| 4 | 1 |
+-----------------+-------+
but then when I try to select the author corresponding to the top X of the result set of the previous query I have an error
I am Trying this SELECT TOP 2 FROM author WHERE (SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC)=idAuthor;
I think it might be because my inside query return 2 rows, and I do a simple SELECT here or that I need a JOIN but i have no ideas how to use it here.
MySQL has no TOP keyword. It does however have a LIMIT keyword. Your query is invalid anyway.
There are a couple of options here. The following is an example of a correlated subquery: https://en.wikipedia.org/wiki/Correlated_subquery
SELECT
a.idAuthor,
a.Name ,
(SELECT COUNT(*) from author_has_publication ahp WHERE
ahp.Author_idAuthor = a.idAuthor) AS publication_count
FROM
author a
ORDER BY
publication_count DESC
LIMIT 2
As the referenced article notes, the above is inefficient as the subquery needs to be re-executed for each row of the result. If you do not actually need the count in the resultset then the below would be more efficient as the subquery is non-correlated and executed only once.
SELECT
a.idAuthor,
a.Name
FROM
author a
INNER JOIN
(select ahp.Author_idAuthor AS idAuthor, COUNT(*) as publication_count
FROM author_has_publication ahp GROUP BY ahp.Author_idAuthor LIMIT 2)
AS TEMP ON TEMP.idAuthor = a.idAuthor

Counting the number of times something appears in a column and recording it

So in order to know how many people in a table are called Johnny I would need to excecute the following query.
Query:
Select count(*) from mytable where first = 'Johnny';
It would give me 2 as the result.
What I wish to do however is record this number in the count column so that the end result comes out like this.
+--------+----------+
| First | COUNT |
+--------+----------+
| Johnny | 2 |
| Diane | 1 |
| Johnny | 2 |
| Harold | 1 |
| Amy | 3 |
| Roy | 2 |
| Amy | 3 |
| Amy | 3 |
| Roy | 2 |
+--------+----------+
Is there any query or procedure capable of resulting in this type of output?
To get your exact output, you need to use a subquery:
select
mytable.First,
counts.`COUNT`
from
mytable
join (
select
First,
count(*) `COUNT`
from
mytable
group by
First
) counts on mytable.First = counts.First;
Try this:
SELECT T1.First, T2.COUNT
FROM mytable T1 JOIN
(SELECT First, COUNT(*) as COUNT
FROM mytable
GROUP BY First) as T2 ON T1.First=T2.First
The result will be:
+--------+----------+
| First | COUNT |
+--------+----------+
| Johnny | 2 |
| Diane | 1 |
| Johnny | 2 |
| Harold | 1 |
| Amy | 3 |
| Roy | 2 |
| Amy | 3 |
| Amy | 3 |
| Roy | 2 |
+--------+----------+

mysql - join problem

I have two tables like below,
mysql> select * from Books ;
+----+------+------------+----------+----------+
| id | name | author_name| category | category2|
+----+------+------------+----------+----------+
| 1 | 1 | Steve | CT001 | CT003 |
| 2 | 2 | John | CT002 | CT002 |
| 3 | 3 | Larry | CT003 | CT002 |
| 4 | 3 | Michael | CT004 | CT004 |
| 5 | NULL | Steven | CT005 | CT005 |
+----+------+------------+----------+----------+
mysql> select * from Codemst ;
+----+------+------------+
| id | code | name |
+----+------+------------+
| 1 | CT001| fiction |
| 2 | CT002| category1 |
| 3 | CT003| etc |
| 4 | CT004| etc2 |
| 5 | CT005| etc3 |
+----+------+------------+
I want to get human readable category name when I query like "select * from Books;"
If there was only one category in the Books table, I think I can use "Join" but, in this case what can I do?
select * from Books b
Inner Join Codemst c1 on b.category = c1.code
inner join codemst c2 on b.category2 = c2.code;
c1.name will hold the readable category, and c2.name the readable category2