MySQL - How to get multiple rows in a single row - mysql

I'm trying to 'CONCAT' the description of multiple rows in a single row.
I have these tables:
tb_employees:
+---------------+---------------+
| id_employee | employee |
+---------------+---------------+
| 1 | Robert Tomson |
| 2 | Jhonatan Weg |
| 3 | Eva Uhte |
+---------------+---------------+
tb_requirements:
+---------------+-----------------+
| id_requirem | requirem |
+---------------+-----------------+
| 11 | Photo |
| 12 | Criminal Record |
| 13 | Shooting Test |
+---------------+-----------------+
tb_details:
+-----------------+---------------------+-------------------------+
| id_detail | id_employee | id_requirem |
+-----------------+---------------------+-------------------------+
| 1 | 1 | 11 |
| 2 | 1 | 12 |
| 3 | 1 | 13 |
| 4 | 2 | 11 |
| 5 | 2 | 13 |
| 6 | 3 | 12 |
| 7 | 3 | 13 |
+-----------------+---------------------+-------------------------+
I have to make a SELECT query to show like this:
+-------------------------+----------------------------------------+
| employee | requirem |
+-------------------------+----------------------------------------+
| Robert Tomson | Photo - Criminal Record - Shooting Test|
| Jhonatan Weg | Photo - Shooting Test |
| Eva Uhte | Criminal Record - Shooting Test |
+-------------------------+----------------------------------------+
To be honest, i really don't know how :S
Any ideas? Thank you for answer.

Use GROUP_CONCAT()
SELECT e.employee, GROUP_CONCAT(r.requirem ORDER BY r.requirem SEPARATOR ' - ') requirements
FROM tb_employees e LEFT JOIN tb_details d
ON e.id_employee = d.id_employee JOIN tb_requirements r
ON d.id_requirem = r.id_requirem
GROUP BY e.id_employee, e.employee
Output:
| EMPLOYEE | REQUIREMENTS |
|---------------|-----------------------------------------|
| Robert Tomson | Criminal Record - Photo - Shooting Test |
| Jhonatan Weg | Photo - Shooting Test |
| Eva Uhte | Criminal Record - Shooting Test |
Here is SQLFiddle demo

Edit:
You should use GROUP_CONCAT and GROUP BY the requirem field.

You need to use group_concat Try the below :
SELECT group_concat(distinct(e.employee) separator ', ') , group_concat(r.requirem separator ', ')
FROM TB_DETAILS d
JOIN TB_EMPLOYEES e ON d.id_employee = e.id_employee
JOIN tb_requirements r ON d.id_requirem = r.id_requirem
| GROUP_CONCAT(DISTINCT(E.EMPLOYEE) SEPARATOR ', ') | GROUP_CONCAT(R.REQUIREM SEPARATOR ', ') |
|---------------------------------------------------|------------------------------------------|
| Robert Tomson, Jhonatan Weg, Eva Uhte | Photo, Criminal Record, Shooting Test, |
| | Photo, Shooting Test, Criminal Record, |
| | Shooting Test |

Related

Not getting desired output in mysql

I am firing a query in mysql but not getting desired output.
this is the code:
select team_name,
sum(semis.points+final.points) as final_points
from semis
inner join final on semis.sid=final.sid
inner join teams on teams.tid=semis.tid
group by semis.tid
union
select team_name,
semis.Points
from semis
inner join teams on semis.tid=teams.tid
left join final on semis.sid=final.sid
where final.sid is null;
OUTPUT:
+-----------------------+--------------+
| team_name | final_points |
+-----------------------+--------------+
| BioTech & BioChem | 7 |
| Chemistry | 7 |
| Botany & Zoology | 7 |
| Physics & Electronics | 17 |
| BCA | 19 |
| BCOM | 11 |
| Gujarati | 10 |
| English | 10 |
| Economics | 20 |
| BCOM | 3 |
| Chemistry | 3 |
| English | 3 |
+-----------------------+--------------+
and the result i want to fetch
+-----------------------+--------------+
| team_name | final_points |
+-----------------------+--------------+
| BioTech & BioChem | 7 |
| Chemistry | 10 |
| Botany & Zoology | 7 |
| Physics & Electronics | 17 |
| BCA | 19 |
| BCOM | 14 |
| Gujarati | 10 |
| English | 13 |
| Economics | 20 |
+-----------------------+--------------+
Adding last 3 values to english,bcom,chemistry increasing it by 3 and making a total of BCOM: 14, Chemistry:10 , English: 13
From the sample data you posted and the expected results it looks like you can do it without UNION, by left joining final and with coalesce() for final.points:
select team_name, sum(semis.points + coalesce(final.points, 0)) as final_points
from semis
inner join teams on teams.tid=semis.tid
left join final on semis.sid=final.sid
group by semis.tid

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 join and concat rows without repeating entries [duplicate]

This question already has answers here:
MySQL DISTINCT on a GROUP_CONCAT()
(6 answers)
Closed 6 years ago.
I have a question about how to merge multiple row output into one row without having the same entry multiple times.
The basic setup is 4 tables:
room
appointments
users
actions
And 2 intermediate tables:
actions_appointments
users_appointments
I post the exact structure of the tables at the end of my post.
Multiple appointments can be made for one entry in the room table (n:1), but one or more users can join appointments (n:n) and one or more actions can be performed (n:n).
The problem is that I don't know how to output a single appointment with each user and action only being displayed ONCE per appointment.
With the example tables at the bottom of this post I basically want this to be my output:
|----------------|-----------|---------------------|-------------|------------------------|
| appointment_id | room_name | datetime | actions | userfullnames |
|----------------|-----------|---------------------|-------------|------------------------|
| 1 | Studio | 2016-09-01 15:30:00 | work, sleep | John Doe, Martin Smith |
| 2 | Office | 2017-04-02 13:00:00 | sleep | John Doe |
|----------------|-----------|---------------------|-------------|------------------------|
But with the queue I came up with I get this:
|----------------|-----------|---------------------|-------------|------------------------|
| appointment_id | room_name | datetime | actions | userfullnames |
|----------------|-----------|---------------------|-------------|------------------------|
| 1 | Studio | 2016-09-01 15:30:00 | work, sleep,| John Doe, Martin Smith,|
| | | | work, sleep | John Doe, Martin Smith |
| 2 | Office | 2017-04-02 13:00:00 | sleep | John Doe |
|----------------|-----------|---------------------|-------------|------------------------|
I mean I kinda get that I screwed up my joins but I'm totally stuck at the moment. Any hints? I feel like the solution is simple but I'm totally blind at the moment.
My queue:
SELECT
appointments.id AS 'appointment_id',
room.name AS 'room_name',
appointments.datetime,
GROUP_CONCAT(actions.name SEPARATOR ', ') AS 'actions',
GROUP_CONCAT(users.givenname, ' ', users.surname SEPARATOR ', ') AS 'userfullnames'
FROM appointments
INNER JOIN actions_appointments
ON appointments.id = actions_appointments.appointments_id
INNER JOIN actions
ON actions_appointments.actions_id = actions.id
INNER JOIN users_appointments
ON users_appointments.appointments_id = appointments.id
INNER JOIN users
ON users_appointments.users_id = users.id
INNER JOIN room
ON appointments.room_id = room.id
GROUP BY
appointments.id;
Table structure:
The basic tables:
|-------------------|
| room |
|-------------------|
| id | name |
|--------|----------|
| 1 | Office |
| 2 | Studio |
|-------------------|
|----------------------------------------|
| appointments |
|--------|---------|---------------------|
| id | room_id | datetime |
|--------|---------|---------------------|
| 1 | 2 | 2016-09-01 15:30:00 |
| 2 | 1 | 2017-04-02 13:00:00 |
|--------|---------|---------------------|
|-----------------------------------------|
| users |
|-----------------------------------------|
| id | username | givenname | surname |
|--------|----------|-----------|---------|
| 1 | j.doe | John | Doe |
| 2 | m.smith | Martin | Smith |
|--------|----------|-----------|---------|
|--------------------|
| actions |
|--------------------|
| id | name |
|--------|-----------|
| 1 | work |
| 2 | sleep |
|--------------------|
The intermediate tables:
|------------------------------|
| actions_appointments |
|------------------------------|
| actions_id | appointments_id |
|------------|-----------------|
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
|------------|-----------------|
|----------------------------|
| users_appointments |
|----------------------------|
| users_id | appointments_id |
|----------|-----------------|
| 1 | 1 |
| 2 | 1 |
| 1 | 2 |
|----------|-----------------|
Edit: The correct queue with DISTINCT
Thanks to Juan.Queiroz and Mike!
SELECT
appointments.id AS 'appointment_id',
room.name AS 'room_name',
appointments.datetime,
GROUP_CONCAT(DISTINCT actions.name SEPARATOR ', ') AS 'actions',
GROUP_CONCAT(DISTINCT users.givenname, ' ', users.surname SEPARATOR ', ') AS 'userfullnames'
FROM appointments
INNER JOIN actions_appointments
ON appointments.id = actions_appointments.appointments_id
INNER JOIN actions
ON actions_appointments.actions_id = actions.id
INNER JOIN users_appointments
ON users_appointments.appointments_id = appointments.id
INNER JOIN users
ON users_appointments.users_id = users.id
INNER JOIN room
ON appointments.room_id = room.id
GROUP BY
appointments.id;
GROUP BY
appointments.id,
room.name,
appointments.datetime

Appending new fields from another JOIN statements in MySQL query

So, I have 3 tables :
guest :
id_guest | name
1 | John
2 | Nick
3 | James
4 | Paul
5 | Chris
6 | Karen
7 | Peter
room :
id_room | status
1 | Clean
2 | Dirty
3 | Dirty
4 | Clean
5 | Clean
6 | Clean
reservation :
id_guest | id_room | date
1 | 1 | 2015-04-15
1 | 1 | 2015-04-16
1 | 1 | 2015-04-17
2 | 3 | 2015-04-15
3 | 4 | 2015-04-15
3 | 4 | 2015-04-16
4 | 2 | 2015-04-16
5 | 2 | 2015-04-17
6 | 2 | 2015-04-18
And this is what the expected output should be :
id_room | status | d04-15 | d04-16 | d04-17 | d04-18
1 | Clean | John | John | John |
2 | Dirty | | Paul | Chris | Karen
3 | Dirty | Nick | | |
4 | Clean | James | James | |
5 | Clean | | | |
6 | Clean | | | |
I have been able to show it until the third field (d04-15) though with the date as values, using :
SELECT room.id_room,
room.status,
reservation.date AS d04-15
FROM room
LEFT JOIN reservation
ON room.id_room = reservation.id_room AND reservation.date = '2015-04-15'
GROUP BY room.id_room
But I'm not sure as to how to display the name there and
appending new fields (d04-16, d04-17, and d04-18) from another JOIN statement.
Any help would be appreciated. Thanks.
The columns returned in a query can't be altered at run time; they have to be statically declared in the SQL SELECT statement.
Here's an example of a statement that can achieve the specified result:
SELECT m.id_room
, m.status
, MAX(IF(r.date='2015-04-15',g.name,NULL)) AS `d04-15`
, MAX(IF(r.date='2015-04-16',g.name,NULL)) AS `d04-16`
, MAX(IF(r.date='2015-04-17',g.name,NULL)) AS `d04-17`
, MAX(IF(r.date='2015-04-18',g.name,NULL)) AS `d04-18`
FROM room m
LEFT
JOIN reservation r
ON r.id_room = m.id_room
AND r.date IN ('2015-04-15','2015-04-16','2015-04-17','2015-04-18')
LEFT
JOIN guest g
ON g.id_guest = r.id_guest
GROUP BY m.id_room

Returning Only First Distinct Value In Sorted MySql Join Query

I have two MySql tables, once for "Locations" and one for "Images". I need to get a list of the most recent Image taken at a particular set of Locations (which is a comma-delimited list), but I only want to return the record for the most recent Image and I've been struggling mightily with getting the right results so far.
So, I have:
Locations:
+---------------------------------------------+
| ID | Name |
|----|----------------------------------------|
| 1 | Indiana |
| 2 | Ohio |
| 3 | Illinois |
+---------------------------------------------+
Images:
+---------------------------------------------+
| ID | User | Location | Date |
|----|-------|-----------|--------------------|
| 1 | Ray | 1 | 2012-06-22 |
| 2 | Robert| 3 | 2011-09-18 |
| 3 | Marie | 1 | 2012-10-01 |
| 4 | Frank | 2 | 2010-12-11 |
| 5 | Debra | 1 | 2008-02-02 |
+---------------------------------------------+
So, right now I have the following:
SELECT Locations.Name, Images.Date, Images.User
FROM Locations INNER JOIN Images ON Locations.ID = Images.Location
WHERE Locations.ID IN ('1','3')
ORDER BY Images.Date DESC
Which returns:
+---------------------------------------------+
| Name | Date | User |
|-------------|-------------|-----------------|
| Indiana | 2012-10-01 | Marie |
| Indiana | 2012-06-22 | Ray |
| Illinois | 2011-09-18 | Robert |
| Indiana | 2008-02-02 | Debra |
+---------------------------------------------+
My question is, how can I get it so that the result returns only the first record with a distinct Location.Name value? So the final, correct result table would look like:
+---------------------------------------------+
| Name | Date | User |
|-------------|-------------|-----------------|
| Indiana | 2012-10-01 | Marie |
| Illinois | 2011-09-18 | Robert |
+---------------------------------------------+
Thanks a lot!
SImply uSe group by::
Select tempTable.Name, tempTable.Date, tempTable.User from
(
SELECT Locations.Name, Images.Date, Images.User, Locations.ID as locationID
FROM Locations
INNER JOIN Images ON Locations.ID = Images.Location
WHERE Locations.ID IN ('1','3')
ORDER BY Images.Date DESC
) as tempTable GROUP BY tempTable.locationID