MySQL查询将位域扩展为单个命名列?

时间:2017-02-16 22:41:07

标签: mysql pivot-table dynamic-sql bit-fields

我有以下问题 我有两个表,第一个表包含一个字符串,如01001101110,每个数字代表表2中提到的技能。

因此,第一个数字显示零,表示该人没有id为1的技能。第二个数字表示该人具有id 2的技能

表1:

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

表2:

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

现在我需要用结果

创建i查询
<html>
<head>
</head>
<body>
<?php

mainProcess();

function mainProcess()
{
$mavalue1 = "";
$mavalue2 = "";

$parts = parse_url($url, PHP_URL_QUERY);   // << It looks like I also have a problem with this line.
parse_str($query, $params);
$mavalue1 = $_GET['param1'];
$mavalue2 = $_GET['param2'];

echo "Valeur de mavalue1 : " . $mavalue1;   // <<< This is where I'm getting the empty value
echo "Valeur de mavalue2 : " . $mavalue2;   // <<< Same problem here
}   
?> 
</body>
</html>

2 个答案:

答案 0 :(得分:1)

我见过很多这样的故事,#34;一位前编码员实现了这一点,现在我们已经坚持下去了。&#34;我想,那里只有一个独立的编码员,他从公司搬到公司,以最聪明,最不易维护的方式实施事情,然后迅速转移到他的下一个受害公司。

我也觉得有人会在varchar中实现一个bitfield,因为他们最终使用一个完整的字节(8位)来存储每个1或0. :facepalm:

无论如何,要解决您的任务,您必须使用动态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,方法是在技能表中的每个条目的select-list中附加一个字段。关键是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