2017-02-16 70 views
2

我有以下问题 我有两个表第一个表包含像01001101110这样的字符串每个数字代表表2中提到的技能。MySQL查询将位域扩展为单个命名列?

所以第一个数字表示零,这意味着该人不具有与ID为1的技术人员的第二个数字表示人确实与ID技能2

表1:

|-----------|-----------------------------| 
|  name  |             skillset           | 
|-----------|-----------------------------| 
|   John  | 01001101110             | 
|-----------|-----------------------------| 

表2:

|-----------|-----------------------------| 
|    id       |              skill              | 
|-----------|-----------------------------| 
|       1    | polite                         | 
|-----------|-----------------------------| 
|      2     | easy going                 | 
|-----------|-----------------------------| 

现在我需要创建我与结果查询

|-----------|-------------------|------------------| 
|  name  |      polite        |   easy going  | 
|-----------|-------------------|------------------| 
|  John   |         0            |            1        | 
|-----------|-------------------|------------------| 
+6

你到底为什么你设计这样的表?规范化数据并查询它变得微不足道。 – David

+0

我以前并没有为这家公司工作的编剧,现在我们必须接受它。但我知道重新设计将是一种选择,但不是我现在正在寻找的那个。

+0

技能列表长度为158个项目,并与两个表格匹配。像这样看待它的想法很巧妙,但也许不是解决问题的最佳方法。所有学分到前编码器 –

回答

1

我见过很多像这样的故事,“一位前编码员实现了这一点,现在我们一直坚持下去。”我想,只有一个个人编码人员,从公司到公司,以最聪明,最不可维护的方式实施事情,然后迅速转移到他的下一个受害者公司。

我也觉得讽刺的是,有人会实现一个varchar位域,因为他们最终会使用一个完整的字节(8位)存储每个1或0 :捂脸:

无论如何,解决你的任务你必须使用动态SQL查询。

实际上,任何数据透视表查询都需要动态SQL,因为在检查列出技能的表之前,您不知道列的数量,但如果不先知道数字,则无法运行查询列。所以你需要运行至少两个查询。

这里的测试数据:

create table table1 (name varchar(20), skillset varchar(200)); 

insert into table1 values ('John', '01001101110110'); 

create table table2 (id int, skill varchar(20)); 

insert into table2 values 
    (1, 'polite'), 
    (2, 'easy going'), 
    (3, 'trustworthy'), 
    (4, 'loyal'), 
    (5, 'helpful'), 
    (6, 'friendly'), 
    (7, 'courteous'), 
    (8, 'kind'), 
    (9, 'obedient'), 
    (10, 'cheerful'), 
    (11, 'thrifty'), 
    (12, 'brave'), 
    (13, 'clean'), 
    (14, 'reverent'); 

现在是产生SQL的动态查询,在选择列表中附加一个字段,在你的技能表中的每个条目的巧妙查询。关键是MySQL的GROUP_CONCAT()函数。

select concat(
    'select name,', 
    group_concat(concat(' mid(skillset,',id,',1) as `',skill,'`')), 
    ' from table1;') as _sql 
from table2; 

上述查询的输出如下:

select name, 
mid(skillset,1,1) as `polite`, 
mid(skillset,2,1) as `easy going`, 
mid(skillset,3,1) as `trustworthy`, 
mid(skillset,4,1) as `loyal`, 
mid(skillset,5,1) as `helpful`, 
mid(skillset,6,1) as `friendly`, 
mid(skillset,7,1) as `courteous`, 
mid(skillset,8,1) as `kind`, 
mid(skillset,9,1) as `obedient`, 
mid(skillset,10,1) as `cheerful`, 
mid(skillset,11,1) as `thrifty`, 
mid(skillset,12,1) as `brave`, 
mid(skillset,13,1) as `clean`, 
mid(skillset,14,1) as `reverent` 
from table1; 

我确信划定与后台蜱列别名,以防万一技能名称中的一个包含特殊字符或空格或与SQL保留字冲突。

然后这可以被运行作为第二查询,其具有以下结果:

+------+--------+------------+-------------+-------+---------+----------+-----------+------+----------+----------+---------+-------+-------+----------+ 
| name | polite | easy going | trustworthy | loyal | helpful | friendly | courteous | kind | obedient | cheerful | thrifty | brave | clean | reverent | 
+------+--------+------------+-------------+-------+---------+----------+-----------+------+----------+----------+---------+-------+-------+----------+ 
| John | 0  | 1   | 0   | 0  | 1  | 1  | 0   | 1 | 1  | 1  | 0  | 1  | 1  | 0  | 
+------+--------+------------+-------------+-------+---------+----------+-----------+------+----------+----------+---------+-------+-------+----------+ 
+1

谢谢,这正是我正在寻找 –

0

使它成为一个SET数据类型;这为您提供了两全其美的解决方案 - 以位为单位存储多达64个预定义选项的任意组合,但仍以字符串形式读取/写入。

简单SELECT skillset FROM tbl WHERE name = 'John'会回来为字符串

"easy going,helpful,friendly,kind" (etc) 

Reference