Разбейте строку на несколько строк с помощью столбца битового поля в MySQL - PullRequest
3 голосов
/ 15 декабря 2011

У меня есть битовое поле, называемое предупреждениями, которое хранится как int.Я хотел бы получить список предупреждений для каждого человека

Допустим, у нас есть таблица

NAME,  WARNINGS
alex,  0
mike,  5
sarah, 2

, где каждый бит целого числа соответствует предупреждению # (позиция бита).В настоящее время это делается в perl с циклом for

for(my $i=0; $i < $warning_size;$i++ ){
     if( (1 << $i ) & $warning != 0){
         print "$name\t" . $i+1 ."\n";
     }
}

Есть ли способ, которым я могу обработать запрос mysql.

Для вышеприведенного примера я хотел бы получить следующий вывод:

name, warning
-------------
mike  1
mike  3
sarah 2

Я пытаюсь свести это к одному оператору выбора,

Спасибо

Ответы [ 4 ]

2 голосов
/ 15 декабря 2011

Попробуйте это -

CREATE TABLE warn_bits(
  b INT(11) NOT NULL
);

INSERT INTO warn_bits VALUES 
  (1),
  (2),
  (3),
  (4),
  (5),
  (6),
  (7),
  (8);

SELECT w.name, wb.b FROM warnings w
  JOIN warn_bits wb
    ON ((w.WARNINGS >> wb.b - 1) & 1) > 0
ORDER BY w.name, wb.b;

+-------+---+
| name  | b |
+-------+---+
| mike  | 1 |
| mike  | 3 |
| sarah | 2 |
+-------+---+

Вы можете расширить таблицу warn_bits для поддержки номеров INT или BIGINT.


Edit2

SELECT w.name, wb.b FROM warnings w
  JOIN (
  SELECT 1 b UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
  SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
  ) wb
    ON ((w.WARNINGS >> wb.b - 1) & 1) > 0
ORDER BY w.name, wb.b;
0 голосов
/ 17 января 2017

Если вы согласны с наличием столбца на предупреждение, вы также можете использовать export_set () и substring () для разбивки битов.

Я предполагаю, что вы используете 4 бита.

bit 1 = "fatal"
bit 2 = "warning"
bit 3 = "error"
bit 4 = "user error"

SELECT
name,
EXPORT_SET(warning,1,0,'',4) AS debugBits,
SUBSTRING(EXPORT_SET(warning,1,0,'',4),1,1) AS hasFatal,
SUBSTRING(EXPORT_SET(warning,1,0,'',4),2,1) AS hasWarning,
SUBSTRING(EXPORT_SET(warning,1,0,'',4),3,1) AS hasError,
SUBSTRING(EXPORT_SET(warning,1,0,'',4),4,1) AS hasUserError
FROM warnings;

который должен вывести что-то вроде:

------|----------|---------|-----------|---------|-------------|
name  |debugBits | hasFatal| hasWarning| hasError| hasUserError|
alex  |      0000|        0|          0|        0|            0|
mike  |      1010|        1|          0|        1|            0|
sarah |      0010|        0|          0|        1|            0|
------|----------|---------|-----------|---------|-------------|

Обратите внимание, что export_set () отображает бит 1 в крайнем левом углу. http://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_export-set

Если вы согласны с колонкой CSV для предупреждений, вы можете использовать make_set ()

SELECT
name,
MAKE_SET(warning,
'fatal',
'warning',
'error',
'userError') AS warningText
FROM warnings

, который даст вам один столбец для предупреждений со списком установленных битовых меток CSV. http://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_make-set

0 голосов
/ 15 декабря 2011

Я думаю, вы просто ищете power(2, x);, попробуйте это: -

mysql> select length(conv(0, 10, 2));
+------------------------+
| length(conv(0, 10, 2)) |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)

mysql> select length(conv(2, 10, 2));
+------------------------+
| length(conv(2, 10, 2)) |
+------------------------+
|                      2 |
+------------------------+
1 row in set (0.00 sec)

mysql> select length(conv(5, 10, 2));
+------------------------+
| length(conv(5, 10, 2)) |
+------------------------+
|                      3 |
+------------------------+
1 row in set (0.00 sec)
0 голосов
/ 15 декабря 2011

Сделать временную таблицу для дробления битов.

mysql> create table bitcrush( bit int );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into bitcrush values (1),(2),(4),(8),(16),(32),(64),(128),(256);
Query OK, 8 rows affected (0.01 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> select name, log2(bit)+1 as warn from c821885 join bitcrush on warn & bit order by name;
+-------+------+
| name  | warn |
+-------+------+
| mike  |    1 |
| mike  |    3 |
| sarah |    2 |
+-------+------+
3 rows in set (0.00 sec)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...