3

我的表格如下

name
| id | name |
|  1 | jon  |
|  2 | mary |

skill
| id | skill | level |
|  1 | C++   | 3     |
|  1 | Java  | 2     |
|  1 | HTML  | 5     |
|  1 | CSS   | 4     |
|  1 | JS    | 5     |
|  2 | PHP   | 4     |
|  2 | Ruby  | 3     |
|  2 | Perl  | 1     |

所以我希望输出是这样的:

| name | skill_1 | lv_1 | skill_2 | lv_2 | skill_3 | lv_3 | skill_4 | lv_4 | skill_5 | lv_5 |
| jon  | C++     | 3    | Java    | 2    | HTML    | 5    | CSS     | 4    | JS      | 5    |
| mary | PHP     | 4    | Ruby    | 3    | Perl    | 1    |         |      |         |      |

我将使用什么类型的 join 或 union 语句?每个人最多只有5个技能。

那么这个 SQL 会是什么样子呢?甚至可能吗?

我完全迷失了,不知道从哪里开始。

4

4 回答 4

5

由于您提到Namea 最多可以有5 Skills,因此可以使用静态查询来解决此问题。

-- <<== 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

输出

╔══════╦═════════╦═════════╦═════════╦═════════╦═════════╗
║ NAME ║ SKILL_1 ║ SKILL_2 ║ SKILL_3 ║ SKILL_4 ║ SKILL_5 ║
╠══════╬═════════╬═════════╬═════════╬═════════╬═════════╣
║ jon  ║ C++     ║ CSS     ║ HTML    ║ Java    ║ JS      ║
║ mary ║ Perl    ║ PHP     ║ Ruby    ║ (null)  ║ (null)  ║
╚══════╩═════════╩═════════╩═════════╩═════════╩═════════╝

简要说明

让我们分解一下。查询中有两个部分。

查询的第一部分是PART 1Skill ,它为每个生成数字序列NameROW_NUMBER它只是使用相关子查询来模仿MySQL不支持的窗口函数。

第二部分PART 2根据PART 1上生成的序号将行转置为列。它用于CASE测试数字的值并返回数字Skill上的关联。如果数字不匹配,则返回一个NULL值。接下来,它聚合每组Name使用的列,MAX()因此SKILL将返回而不是NULL如果有的话。

更新 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

输出

╔══════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╗
║ 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)  ║
╚══════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╝
于 2013-06-02T07:44:10.010 回答
2

这也可能是可能的解决方案!

询问

select a.name, 
(select skill  from skill where skill.id=a.id limit 0,1  ) as skill_1,
(select skill  from skill where skill.id=a.id limit 1,1) skill_2,
(select skill from skill where skill.id=a.id limit 2,1 ) skill_3,
(select skill from skill where skill.id=a.id limit 3,1) skill_4,
(select skill from skill  where skill.id=a.id limit 4,1) skill_5
 from name a

输出

在此处输入图像描述

于 2013-06-02T09:51:55.447 回答
1

我理解你所谓的数据透视表,这里有一个很好的教程。为了实现您所追求的,您需要将skill表的架构稍微更改为...

| id | skill_id | skill |
|  1 | 1        | C++   |
|  1 | 2        | Java  |
|  1 | 3        | HTML  |
|  1 | 4        | CSS   |
|  1 | 5        | PHP   |
|  2 | 1        | RUBY  |
|  2 | 2        | PERL  |
|  2 | 3        | JS    |

尝试这个:

SELECT n.name,
, if(s.skill_id=1, s.skill, '') as 'skill_1'
, if(s.skill_id=2, s.skill, '') as 'skill_2'
, if(s.skill_id=3, s.skill, '') as 'skill_3'
, if(s.skill_id=4, s.skill, '') as 'skill_4'
, if(s.skill_id=5, s.skill, '') as 'skill_5'
FROM name n
INNER JOIN skill s ON n.id = s.id
group by s.skill
LIMIT 0, 10
于 2013-06-02T07:41:52.977 回答
1

我认为没有连接可以回答这种类型的输出,所以最好从代码中处理,但你可以使用 group_concat()withgroup by

于 2013-06-02T07:42:05.690 回答