строки mySQL SELECT, в которых установлен определенный бит целого числа - PullRequest
6 голосов
/ 02 февраля 2012

Мне нужно выполнить запрос на выборку в таблице сообщений, в которой установлен определенный бит целого числа.Целое число представляет набор категорий в битовой маске: например,

1 => health
2 => marketing
3 => personal
4 => music
5 => video
6 => design
7 => fashion
8 => ......

Пример данных:

id | categories | title
1  | 11         | bla bla
2  | 48         | blabla, too

Мне нужен запрос mysql, который выбирает публикации, которыеотмечен определенной категорией.Допустим, «все публикации видео». Это означает, что мне нужен результирующий набор сообщений, в которых установлен 5-й бит столбца категории (например, 16,17,48 ....)

SELECT * FROM postings WHERE ....????

Есть идеи?

Ответы [ 3 ]

11 голосов
/ 02 февраля 2012

Вы можете использовать побитовые операторы, подобные этому.Для видео (бит 5):

WHERE categories & 16 = 16

Замените значение 16, используя следующие значения для каждого бита:

1 = 1
2 = 2
3 = 4
4 = 8
5 = 16
6 = 32
7 = 64
8 = 128

Это происходит от младшего значащего бита к старшему, чтопротивоположность тому, как думает большинство программистов.Они также начинаются с нуля.

3 голосов
/ 02 февраля 2012

Как насчет

SELECT * FROM postings WHERE (categories & 16) > 0; -- 16 is 5th bit over

Одна из проблем заключается в том, что вы, вероятно, не попадете в индекс, поэтому вы можете столкнуться с проблемами перфорирования, если это большой объем данных.

Некоторые базы данных (такие как PostgreSQL) позволяют вам определять индекс для выражения, подобного этому. Я не уверен, есть ли у MySQL эта функция. Если это важно, возможно, вы захотите разбить их на отдельные логические столбцы или новую таблицу.

0 голосов
/ 02 февраля 2012

SQL (не только mySQL) не подходит для побитовых операций. Если вы сделаете побитовое И, то вы запустите сканирование таблицы, поскольку SQL не сможет использовать какой-либо индекс и должен будет проверять каждую строку по одному за раз.

Было бы лучше, если бы вы создали отдельную таблицу «Категории» и правильно индексированную таблицу «многие ко многим» PostingCategories, чтобы соединить их.

UPDATE

Для людей, которые настаивают на том, что растровые поля не являются проблемой, полезно проверить BIT проблемы Джо Селко . В нижней части статьи приведен список серьезных проблем, вызванных растровыми изображениями.

Что касается комментария о том, что общий оператор не может быть правильным, обратите внимание # 10 - он ломает 1NF, так что да, битовые поля плохие:

  1. Данные не читаются. ...
  2. Ограничения b #### для записи ....
  3. Вы ограничены двумя значениями в каждом поле. Это очень ограничительно; даже половой код ISO не может вписаться в такой столбец ...
  4. В битовой маске (или в однобитовых флагах) нет временного элемента. Например, флаг «is_legal_adult_flg» ... ДАТА для даты рождения (всего 3 байта) будет содержать полный факт и позволит нам вычислить то, что нам нужно знать; это тоже всегда будет правильно. ...
  5. Вы обнаружите, что использование флагов приведет к разделению статуса сущности на несколько таблиц ....
  6. Битовые флаги предполагают избыточность. В системе, которую я только что упомянул, в одной таблице были «is_active_flg» и «is_completed_flg». Завершенный аукцион не активен и наоборот. Это тот же факт в двух флагах. Психология человека (и английский язык) предпочитает слышать утвердительную формулировку (помните старую песню «Да, у нас сегодня нет бананов!»?). Все эти битовые флаги и проверка последовательности заменяются двумя наборами таблиц переходов между состояниями, один для заявок и один для поставок. Для получения подробной информации об ограничениях перехода состояний. История каждого аукциона теперь находится в одном месте и должна соответствовать бизнес-правилам.
  7. К тому времени, когда вы разберете столбец битовой маски и выбросите поля, которые вам не нужны, производительность не улучшится по сравнению с более простыми типами данных.
  8. Группировка и упорядочивание по отдельным полям - настоящая боль. Попытайся.
  9. Вы должны проиндексировать весь столбец, поэтому, если вам не повезет и вы не получите их в правильном порядке, вы застрянете в сканировании таблицы.
  10. Поскольку битовая маска не находится в первой нормальной форме (1NF), у вас есть все аномалии, которые мы хотели бы избежать в СУБД.

Я бы также добавил, как насчет NULL? Как насчет отсутствующих флагов? Что если что-то не является ни истинным, ни ложным?

Наконец, что касается утверждения о сжатии, большинство баз данных упаковывают битовые поля в байты и целые числа внутри. В этом случае поле растрового изображения не предлагает никакого сжатия. Другие базы данных (например, PostgreSQL) на самом деле имеют логический тип, который может быть true / false / unknown. Это может занять 1 байт, но это не много памяти и прозрачное сжатие доступно, если таблица становится слишком большой.

На самом деле, если таблица становится большой, проблемы с полями растрового изображения становятся намного серьезнее. Сохранение нескольких МБ в таблице ГБ не принесет пользы, если вы вынуждены использовать сканирование таблицы или потеряли способность группировать

...