我正在设计一个数据结构,并想知道我是否遗漏了这样做的任何事情。
假设我有一个类型为int的列DAY。
1 : Monday
2 : Tuesday
4 : Wednesday
8 : Thursday
16 : Friday
32 : Saturday
64 : Sunday
如果我想在星期一和星期五存储,我会在DAY列中输入17。如果我想在星期二和星期三存储,我会输入6等。
这是存储数据的有效方式吗?如果我想选择一个包含星期六的记录的位置以及任何天数,星期六而不是星期三的变化,查询将如何显示。这可能吗?它会快吗?
这个概念叫什么?
答案 0 :(得分:3)
有些人可能会告诉你这是代码'气味',因为它代表非规范化,但我认为这是一个完全有效的使用位掩码字段:
-- Contains Saturday and any other combination of days
SELECT * FROM Table
WHERE (DayBitColumn & 32) = 32
-- Contains Saturday and any other combination of days, except Wednesday
SELECT * FROM Table
WHERE (DayBitColumn & 32) = 32 AND (DayBitColumn & 4) = 0
编辑:正如@Andriy M指出的那样,这可以更简洁地写成:
SELECT * FROM Table
WHERE (DayBitColumn & 36) = 32
[ '&安培;'按位AND]
答案 1 :(得分:2)
问题的症结在于
这可能吗?是它会快吗?
是的,这是可能的 是和否 - 这取决于您的数据分布。
如果将它们存储在位字段中,SQL Server仍会在内部将它们存储到单个字节中,这意味着您可以获得所有存储的优点,而且不必手动进行位屏蔽。 为什么重复这项工作?
无论是单独存储还是单个字段存储,索引都无济于事。
但是,如果您将其标准化并将其存储在辅助表中,请说像Event_Day类似
EventID | Day
1 2
1 4
仅存储事件发生的日期,然后您刚刚构建了物化索引。当然,你必须平衡这一点的好处,而不是必须一直PIVOT数据,以产生一个很好的每周时间表。
答案 2 :(得分:1)
1)有可能吗?是。我在我当前的项目数据库中使用它,这涉及协调检查。如果要排除某个项目,我会在跳过列中标记它。因为跳过某些东西有很多理由,我想知道为什么跳过它,我用按位运算符设置标志。
2)速度快吗?在有限的情况下。 WHERE skip = 0
?快速。 WHERE skip & 4 = 4
...好吧,我将来会进行表格扫描,并查询并操作所有值以完成查询。
快速插入,快速选择数字范围,但如果您想知道设置了星期一标志的所有内容,请慢一点。如果您想知道设置了星期日标志并知道查询为>= 64
的所有内容,请快速。
Mike Wheat's answer对您的其他问题有正确的疑问,因此我不会重复这些问题。再次注意,他们需要一个表扫描,并不会很快。如果您确实将它们作为单独的列,并且您对每个列进行索引,那么您将消耗大量空间来制作索引。除非它们覆盖索引,否则您将看到表格中的有限好处...星期六+除星期三之外的所有内容仍然需要扫描星期六或整个星期三的每列配置。在这种情况下扫描所有这些内容的表可能最终比根据数据散布等更快地搜索。