Reputation: 41
I have 2 tables
tbl_Participants
id
group_name
firstname
lastname
tbl_Groups
id
group_name
But I have difficulties joining the tables to show the below layout.
Group Name | Member 1 | Member 2 | Member 3
This query shows a list but not in the layout above:
select gr.firstname, gr.lastname, gr.group_name
from tbl_Participants gr inner join tbl_Group gr2
ON gr.group_name = gr2.group_name
order by group_name
Upvotes: 1
Views: 68
Reputation: 164139
For MySQl 8.0+ you can use ROW_NUMBER()
window function to rank member names inside their groups alphabetically and after filtering only the first 3 names of each group use conditional aggregation to get the result that you want:
SELECT group_name,
MAX(CASE WHEN rn = 1 THEN name END) Member1,
MAX(CASE WHEN rn = 2 THEN name END) Member2,
MAX(CASE WHEN rn = 3 THEN name END) Member3
FROM (
SELECT group_name,
CONCAT(lastname, ' ', firstname) name,
ROW_NUMBER() OVER (PARTITION BY group_name ORDER BY lastname, firstname) rn
FROM tbl_Participants
) t
WHERE rn <= 3
GROUP BY group_name
For prior versions use aggregation with GROUP_CONCAT()
and SUBSTRING_INDEX()
to split the names list:
SELECT group_name,
SUBSTRING_INDEX(names, ',', 1) Member1,
CASE WHEN counter > 1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(names, ',', 2), ',', -1) END Member2,
CASE WHEN counter > 2 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(names, ',', 3), ',', -1) END Member3
FROM (
SELECT group_name,
COUNT(*) counter,
GROUP_CONCAT(CONCAT(lastname, ' ', firstname) ORDER BY lastname, firstname) names
FROM tbl_Participants
GROUP BY group_name
) t
See a simplified demo.
If there are groups in tbl_Groups
with no rows in tbl_Participants
and you want them in the results, it's easier to do it with UNION ALL
than a join.
Add to the above queries:
UNION ALL
SELECT g.group_name, null, null, null
FROM tbl_Groups g
WHERE NOT EXISTS (
SELECT 1
FROM tbl_Participants p
WHERE p.group_name = g.group_name
)
Upvotes: 1