我在SQL Server数据库中有两个表。一个表BusinessOperations
具有关于此业务对象的各种信息,另一个表OperationType
纯粹是一个按位标志表,如下所示:
| ID | Type | BitFlag |
| 1 | Basic-A | -2 |
| 2 | Basic | -1 |
| 3 | Type A | 0001 |
| 4 | Type B | 0002 |
| 5 | Type C | 0004 |
| 6 | Type D | 0008 |
| 7 | Type E | 0016 |
| 8 | Type F | 0032 |
BitFlag列是varchar列,以'0001'
作为示例插入位标志。在BusinessOperations
表中,有一列使用这些表的应用程序根据应用程序UI中选择的内容更新它。例如,我有一种类型,其中选择了Basic
,Type A
和Type B
类型。 BusinessOperations
中的列值为3.
基于此,我正在尝试编写一个查询,它将显示如下:
| ID | Name | Description | OperationType |
| 1 | Test | Test | Basic, Type A, Type B |
以下是BusinessOperations
表的实际布局(Basic-A
和Basic
是位列:
| ID | Name | Description | Basic-A | Basic | OperationType |
| 1 | Test | Test | 0 | 1 | 3 |
没有任何内容可以将这两个表相互关联,因此我无法执行连接。我对按位操作非常缺乏经验,并且对于如何构造用于分析此数据的select查询完全不知所措。我觉得它需要STUFF
或CASE
,但我不知道如何才能显示这些类型,而不仅仅是生成的BitFlag。
SELECT ID, Name, Description, OperationType
FROM OperationType
ORDER BY ID
答案 0 :(得分:0)
在BusinessOperations表中,Basic-A和Basic字段是位字段,这只是另一种说法,该值只能是1或0.可以将其视为布尔值True / False。因此,在您的查询中,您可以检查每个内容,以确定是否包含“基本A”和“基本”。
OperationType可能是一个id,您可以在OperationsType表中查找以获取Type和BitFlag。如果不完全理解您的数据,看起来您可以为该部分进行连接。希望这是正确的大方向。如果没有,请告诉我。
答案 1 :(得分:0)
由于您要将OperationType
中的标记存储为VARCHAR
,因此您需要做的第一件事就是将CONVERT
或CAST
字符串添加到一个数字中我们可以进行适当的按比例比较。我对SQL Server略有不熟悉,但在演员表之前你可能需要remove the leading zeroes。因此,我们所需SQL中的OperationType
列看起来像
CONVERT(INT, BitFlag)
然后,将其与我们的OperationType
列进行比较将类似于
CONVERT(INT, BitFlag) & OperationType
完整查询看起来像(原谅我再次缺乏SQL Server专业知识):
SELECT bo.ID, bo.Name, bo.Description, ot.Type
FROM BusinessOperations AS bo
JOIN OperationType AS ot
ON CONVERT(INT, ot.BitFlag) & OperationType <> 0
上述查询将有效地为您提供OperationTypes的列表。如果您在一行中绝对需要它们,请参阅other answers以了解如何在SQL Server中模拟GROUP_CONCAT
之类的内容。 免责声明:加入位掩码并不能保证性能。
此答案未解决的另一个问题是您的旧版Basic和Basic-A字段。就个人而言,我会做两件事之一:
OperationType
表中移除它们,并让应用程序根据Basic
和Basic-A
列适当地启用这两个。OperationType
表中,并让应用程序根据需要填充旧列和OperationType
列。正如Aaron Bertrand在评论中所说,这根本不是Bitmasking的问题。拥有一个将BusinessOperations.ID
与OperationType.ID
相关联的众多表格可以更好地解决您的所有问题。