Хранить несколько битовых значений в одном столбце таблицы - PullRequest
3 голосов
/ 10 марта 2012

Мне нужно хранить какое-то расписание дня недели в базе данных, где я могу запланировать запись (скажем, она представляет задачу) на день или несколько дней недели. Мне нужно хранить его в одном столбце, чтобы его было легко сохранять и извлекать. Затем каждый день я выбираю записи, в которых расписание соответствует текущему дню недели, что-то вроде: получите все записи с расписанием в день недели 7.

То, что мне пришло в голову, - это серия из 7 битов, каждый из которых представляет день недели, где 0 означает не расписание, а 1 означает расписание. Например: «1111111» для случая ежедневного задания и «1000000» для задания, которое выполняется только в первый день недели.

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

У меня здесь два вопроса:

  1. Как лучше всего хранить данные такого типа в SQL Server 2008? Таким образом, это позволяет легко запрашивать в зависимости от текущего дня недели.

  2. Какие есть лучшие альтернативы вышеуказанному подходу. Пожалуйста, мне нужны эффективные и простые в реализации решения.

Ответы [ 3 ]

7 голосов
/ 10 марта 2012

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

, например:

CREATE TABLE [dbo].[testBF](
    [field1] [varchar](max) NOT NULL,
    [field2] [varchar](max) NOT NULL,
    [bitfield] [int] NOT NULL CONSTRAINT [DF_testBF_bitfield]  DEFAULT ((0))
) ON [PRIMARY]

Затем для выбора:

SELECT field1, field2,
       CASE WHEN (bitfield & 1) = 1 THEN 'monday ' ELSE '' END + 
       CASE WHEN (bitfield & 2) = 2 THEN 'tuesday ' ELSE '' END +
       CASE WHEN (bitfield & 4) = 4 THEN 'wednesday ' ELSE '' END +
       CASE WHEN (bitfield & 8) = 8 THEN 'thursday ' ELSE '' END +
       CASE WHEN (bitfield & 16) = 16 THEN 'friday' ELSE '' END as [days of week]
FROM testBF

Чтобы найти все дни, которые содержат флаг вторника (вторник - 2-й бит или 2 ^ 1 или 2)

SELECT * 
FROM aTable
WHERE (bitfield & 2) = 2

или

SELECT * 
FROM aTable
WHERE (bitfield & 2) != 0

Обратите внимание, что шаблон во втором случае будетработать для любого бита - то есть для пятницы (5-й бит или 2 ^ 4 или 16) будет

SELECT * 
FROM aTable
WHERE (bitfield & 16) != 0

Наконец, общий случай ... передать число (1 для понедельника) вы получите

SELECT * 
FROM aTable
WHERE (bitfield & POWER(2,@inNumOfWeekday-1)) != 0

Мне кажется, что это большая работа, когда вы можете просто сохранить ее как 5 (или 7-битные поля), но именно так вы можете это сделать.

Для большего количества примеров посмотрите на суть, которую я написал для другого вопроса:

https://gist.github.com/1846338

и ответ:

https://stackoverflow.com/a/9302106/215752

1 голос
/ 10 марта 2012

Вы говорите о «битовой маске».Это удобные устройства, поскольку вы можете применять двоичную математику к ним, чтобы легко проверить значения, но они требуют небольшой настройки.Более подробно это будет выглядеть примерно так.

-- You will want to work with constants
DECLARE @Mon INT, @Tue INT, @Wed INT, @Thu INT, @Fri INT, @Sat INT, @Sun INT

SET @Mon = POWER(2,0) -- 1
SET @Tue = POWER(2,1) -- 2
SET @Wed = POWER(2,2) -- 4
SET @Thu = POWER(2,3) -- 8
SET @Fri = POWER(2,4) -- 16
SET @Sat = POWER(2,5) -- 32
SET @Sun = POWER(2,6) -- 64

-- Set Monday and Wednesday
UPDATE T SET Schedule = @Mon | @Wed

-- Find all tasks scheduled on Tuesday
SELECT * FROM T WHERE Schedule & @Tue = @Tue

-- Find all tasks scheduled on Tuesday and Saturday
SELECT * FROM T WHERE Schedule & @Tue | @Sat = @Tue | @Sat
0 голосов
/ 10 марта 2012

Я не уверен, что вы подразумеваете под простыми запросами.Это все легко, как только вы оберните это в функцию.Вариант для простых специальных запросов может состоять в том, чтобы иметь легко читаемые строковые поля и использовать некоторые процессы манипуляции со строками.Пример:

UPDATE T SET Schedule = 'M|W|H'

SELECT * FROM T WHERE CHARINDEX(Schedule, 'M') > -1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...