2012-03-10 16 views
2

ある日のスケジュールをデータベースに保存する必要があります。ここでは、1日または複数の曜日のレコードをスケジュールできます。保存して検索するのが簡単にできるように、1つの列に格納する必要があります。そして、毎日私はスケジュールが現在の曜日と一致するレコードを選択します。曜日のスケジュールに合わせてすべてのレコードを取得します。複数のビット値を1つのテーブル列に格納する

私の心には、それぞれが1日を表す一連の7ビットがあります0はスケジュールではなく、1はスケジュールされたスケジュールを意味します。たとえば、毎日のタスクの場合は「1111111」、週の最初の曜日にのみ実行されるタスクの場合は「1000000」です。

レコードは、私が知らない任意の日の組み合わせでスケジュールされる場合があります。したがって、検索の唯一の入力は、検索する曜日です。

私はここに2つの質問があります

  1. SQL Server 2008でこのタイプのデータを格納するための最良の方法は何ですか?現在の曜日に応じて簡単にクエリを実行できるようにします。

  2. 上記のアプローチのより良い代替方法は何ですか?効率的で簡単にソリューションを実装する必要があります。

+2

7ビットではなく、1つの列に7ビットをクランチするのは本当に簡単ですか?私は別の列がより簡単になると思います。 –

答えて

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番目のビットまたは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

+0

質問私は上記のように私の他の答えで示しています。月曜日と火曜日は '3'か' 1 | 2 '。ウィキペディアは私がこれまで以上に説明する:http://en.wikipedia.org/wiki/Bit_field – Hogan

+0

私はホーガンに同意します。ビット数はうまくいくが、残虐なように見え、他の人を混乱させる可能性が最も高い。可能なすべての組み合わせは、1ビットの列(1バイト)に収まります。これは7ビットの列とほぼ同じです。したがって、いずれの決定にもストレージの利点はありません。 – brian

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

これまでのように単一のセレクタを追加することはできますが、それらをORする方がはるかに安全です。例えば ​​'(@Tue + @Sat)+(@Tue + @Mon)'はあなたの例を考えればうまくいくように見えますが、失敗するでしょう。しかし、 '(@Tue | @Sat)| (@Tue | @Mon) 'うまく動作します。 – Hogan

+0

ありがとう、私はいつかこれをテストしなければならないでしょう。ビットマスクは楽しいですが、私はまだSQLで作成する必要があります。 – Malk

+0

私の答えで要点をつかむと、実際にそれを見ることができます! – Hogan

0

簡単なクエリの意味がわかりません。一度ファンクションでラップすると簡単です。簡単なアドホッククエリのオプションは、読みやすい文字列フィールドを持ち、いくつかの文字列操作プロセスを使用することです。例:

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

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

私はあなたの文字列操作ソリューションが好きかもしれませんが、多少のバリエーションがあります:デリミタを必要とせずに、文字の代わりに平日の数を追加してください。優先順位はより効率的なアプローチになります。とにかくありがとう! – Lamar

関連する問題