2012-03-10 64 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

相關問題