Since you have mentioned that a Name
can have a maximum of 5 Skills
, this problem can be done using static query.
-- <<== PART 2
SELECT Name,
MAX(CASE WHEN RowNumber = 1 THEN Skill END) Skill_1,
MAX(CASE WHEN RowNumber = 2 THEN Skill END) Skill_2,
MAX(CASE WHEN RowNumber = 3 THEN Skill END) Skill_3,
MAX(CASE WHEN RowNumber = 4 THEN Skill END) Skill_4,
MAX(CASE WHEN RowNumber = 5 THEN Skill END) Skill_5
FROM
( -- <<== PART 1
SELECT a.Name,
b.Skill,
(
SELECT COUNT(*)
FROM Skill c
WHERE c.id = b.id AND
c.Skill <= b.Skill) AS RowNumber
FROM Name a
INNER JOIN Skill b
ON a.id = b.id
) x
GROUP BY Name
OUTPUT
╔══════╦═════════╦═════════╦═════════╦═════════╦═════════╗
║ NAME ║ SKILL_1 ║ SKILL_2 ║ SKILL_3 ║ SKILL_4 ║ SKILL_5 ║
╠══════╬═════════╬═════════╬═════════╬═════════╬═════════╣
║ jon ║ C++ ║ CSS ║ HTML ║ Java ║ JS ║
║ mary ║ Perl ║ PHP ║ Ruby ║ (null) ║ (null) ║
╚══════╩═════════╩═════════╩═════════╩═════════╩═════════╝
BRIEF EXPLANATION
Let's breakdown it down. There are two parts in the query.
The first part, which is PART 1, of the query generates the sequence of number on Skill
for every Name
. It just uses correlated subquery to mimic a window function ROW_NUMBER
which MySQL
does not support.
The second part, PART 2, transpose the rows into columns based on the sequential number generated on PART 1. It uses CASE
to test the value of the number and returns the Skill
associated on the number. If the number does not match it returns a NULL
value. Next, it aggregates the column for every group of Name
using MAX()
so SKILL
will be returned instead of NULL
if there is any.
UPDATE 1
SELECT Name,
MAX(CASE WHEN RowNumber = 1 THEN Skill END) Skill_1,
MAX(CASE WHEN RowNumber = 1 THEN Level END) Level_1,
MAX(CASE WHEN RowNumber = 2 THEN Skill END) Skill_2,
MAX(CASE WHEN RowNumber = 2 THEN Level END) Level_2,
MAX(CASE WHEN RowNumber = 3 THEN Skill END) Skill_3,
MAX(CASE WHEN RowNumber = 3 THEN Level END) Level_3,
MAX(CASE WHEN RowNumber = 4 THEN Skill END) Skill_4,
MAX(CASE WHEN RowNumber = 4 THEN Level END) Level_4,
MAX(CASE WHEN RowNumber = 5 THEN Skill END) Skill_5,
MAX(CASE WHEN RowNumber = 5 THEN Level END) Level_5
FROM
(
SELECT a.Name,
b.Skill,
(
SELECT COUNT(*)
FROM Skill c
WHERE c.id = b.id AND
c.skill <= b.skill) AS RowNumber,
b.Level
FROM Name a
INNER JOIN Skill b
ON a.id = b.id
) x
GROUP BY Name
OUTPUT
╔══════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╗
║ NAME ║ SKILL_1 ║ LEVEL_1 ║ SKILL_2 ║ LEVEL_2 ║ SKILL_3 ║ LEVEL_3 ║ SKILL_4 ║ LEVEL_4 ║ SKILL_5 ║ LEVEL_5 ║
╠══════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╣
║ jon ║ C++ ║ 3 ║ CSS ║ 4 ║ HTML ║ 5 ║ Java ║ 2 ║ JS ║ 5 ║
║ mary ║ Perl ║ 1 ║ PHP ║ 4 ║ Ruby ║ 3 ║ (null) ║ (null) ║ (null) ║ (null) ║
╚══════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╝