2017-02-16 2 views
2

У меня есть следующая проблема У меня есть две таблицы, первая таблица содержит строку типа 01001101110, каждая цифра представляет собой навык, упомянутый в таблице 2.Запрос MySQL для расширения битового поля в отдельные столбцы имен?

Таким образом, первая цифра показывает ноль, что означает, что человек не имеет навыка с идентификатором 1. вторая цифра показывает, что человек имеет навык с идентификатором 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. : 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 для динамического запроса путем добавления одного поля в списке выбора для каждой записи в вашей таблице навыков. Ключом является функция 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

Смежные вопросы