2012-03-10 70 views
2

我需要在数据库中存储某种星期的调度,在那里我可以安排一天或一周的多天中的某个记录(比如说表示任务) 。我需要将它存储在一列中,以便保存和检索。然后,我每天选择时间表与当前星期几相匹配的记录,例如:将所有记录与计划匹配的星期几交给第7周。在一个表格列中存储多个位的值

我想到的是一系列7位,每一个代表一天0代表不计划,1代表计划。例如:“1111111”表示日常任务的情况,“1000000”表示仅在一周的第一天运行的任务。

要清楚的是,记录可以按照我不知道的任何日期组合进行排定,因此检索中唯一的输入将是星期几来搜索。

我有两个问题在这里:

  1. 什么是存储在SQL Server 2008中这种类型的数据的最佳方式?根据当前的星期几,可以轻松查询。

  2. 什么是更好的替代上述方法。请我需要高效且易于实施的解决方案。

+2

如何将七位数据分成一列而不是七位?我会认为单独的列会更容易。 – 2012-03-10 05:16:08

回答

7

你可以存储此作为一个位域,然后使用布尔逻辑运算符来获取值

例如:

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^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

+0

假设我想要在星期一和星期二的时间安排,如何在位域中进行编码,以及如何正确查询它? – Lamar 2012-03-10 03:20:54

+0

我在其他答案中显示的查询,如上面星期一和星期二是'3'或'1 | 2'。维基百科解释比我以往任何时候都要好:http://en.wikipedia.org/wiki/Bit_field – Hogan 2012-03-10 03:27:04

+0

我同意Hogan。有点数学可能会起作用,但似乎太过矫枉过正,很可能会让其他人感到困惑。所有可能的组合都可以放入1个tinyint(1字节)列中,与7位列大致相同,因此这两种决策都没有存储优势。 – brian 2012-03-10 03:38:12

1

你是在谈论一个 “位掩码”。这些都是方便的设备,因为您可以对它们应用二进制数学来轻松检查值,但它们需要一些设置。为了扩大这一点,它会看起来像这样。

-- 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

尽管您可以像添加单个选择器一样添加单个选择器,但它们更安全。例如,'(@Tue + @Sat)+(@Tue + @Mon)'看起来像它可以在你的例子中工作,但它会失败。但是,(@Tue | @Sat)| (@Tue | @Mon)'工作正常。 – Hogan 2012-03-10 03:22:11

+0

谢谢,我不得不在某个时候测试一下。位掩码很有趣,但我还没有需要在SQL中创建一个。 – Malk 2012-03-10 03:30:47

+0

在我的答案中抓住要点,你可以看到它的行动! – Hogan 2012-03-10 03:34:08

0

我不知道你的意思是容易查询。一旦你把它包装在一个函数中,这很容易。轻松即席查询的选项可能是容易读取的字符串字段,并使用一些字符串操作进程实现。例如:

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

SELECT * FROM T WHERE CHARINDEX(Schedule, 'M') > -1 
+0

我喜欢你的字符串操作解决方案,也许有一点变化:增加工作日而不是字母,而不需要分隔符。尽管优先考虑更高效的方法。不管怎么说,还是要谢谢你! – Lamar 2012-03-10 03:58:42

相关问题